日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

中国剩余定理(CRT)扩展中国剩余定理(exCRT)

發布時間:2024/4/11 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 中国剩余定理(CRT)扩展中国剩余定理(exCRT) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

中國剩余定理(也叫孫子定理)并不是很復雜,由于最近用到了,以前學的時候還不寫博客,所以現在補一下

中國剩余定理(CRT)

問題

給出nnn個同余方程
x≡a1(modp1)x≡a2(modp2)????????x≡an(modpn)\begin{aligned} x&\equiv a_1\pmod{p_1}\\ x&\equiv a_2\pmod{p_2}\\ ··&\ \ \ \ \ ···\ \ \ \ \ \ \ \ ···\\ x&\equiv a_n\pmod{p_n}\\ \end{aligned} xx??x?a1?(modp1?)a2?(modp2?)???????????????????an?(modpn?)?
保證所有的ppp兩兩互質
求最小自然數解xxx

做法

我們令P=∏i=1npiP=\prod_{i=1}^n p_iP=i=1n?pi?
容易發現,x&lt;Px&lt;Px<P
證明,若現在求出一個xxx滿足條件且x≥Px\ge PxP
那么(xmod&ThinSpace;&ThinSpace;P)(x\mod P)(xmodP)一定也滿足條件且(xmod&ThinSpace;&ThinSpace;p)&lt;P(x\mod p)&lt;P(xmodp)<P
我們考慮對于一個限制x≡ai(modpi)x\equiv a_i\pmod{p_i}xai?(modpi?),我們要進行一種操作,使得其它n?1n-1n?1ppp的模意義下值不變,模pip_ipi?意義下的值從000變為aia_iai?
考慮如果我們加上的數是X?PpiX*\frac{P}{p_i}X?pi?P?形式的,那么我們就可以滿足“其它n?1n-1n?1ppp的模意義下值不變”,由于保證了所有ppp兩兩互質,所以Ppi?≡0(modpi)\frac{P}{p_i}\not\equiv0\pmod{p_i}pi?P???0(modpi?)
Ppi≡vi(modpi)\frac{P}{p_i}\equiv v_i\pmod{p_i}pi?P?vi?(modpi?)
那么只要加上(aivi?1(modPpi))Ppi(a_iv_i^{-1}\pmod{\frac{P}{p_i}})\frac{P}{p_i}(ai?vi?1?(modpi?P?))pi?P?就可以滿足這條限制
最后求出xxx后再模PPP就好了

例題

竟然有模板題。。。
洛谷P3868 [TJOI2009]猜數字
有個要注意的地方是這里的逆元應用擴展歐幾里得(exGCD)求,另外由于模數過大,需要用到慢速乘(復雜度Θ(logn)\Theta(logn)Θ(logn)),可以用杜教乘優化(復雜度Θ(1)\Theta(1)Θ(1),我的這篇博客里有提到)

代碼

ac代碼(其實也是板子)

#include<cstdio> #include<cctype> #include<algorithm> namespace fast_IO {const int IN_LEN=10000000,OUT_LEN=10000000;char ibuf[IN_LEN],obuf[OUT_LEN],*ih=ibuf+IN_LEN,*oh=obuf,*lastin=ibuf+IN_LEN,*lastout=obuf+OUT_LEN-1;inline char getchar_(){return (ih==lastin)&&(lastin=(ih=ibuf)+fread(ibuf,1,IN_LEN,stdin),ih==lastin)?EOF:*ih++;}inline void putchar_(const char x){if(oh==lastout)fwrite(obuf,1,oh-obuf,stdout),oh=obuf;*oh++=x;}inline void flush(){fwrite(obuf,1,oh-obuf,stdout);} } using namespace fast_IO; #define getchar() getchar_() #define putchar(x) putchar_((x)) #define rg register typedef long long LL; template <typename T> inline T max(const T a,const T b){return a>b?a:b;} template <typename T> inline T min(const T a,const T b){return a<b?a:b;} template <typename T> inline void mind(T&a,const T b){a=a<b?a:b;} template <typename T> inline void maxd(T&a,const T b){a=a>b?a:b;} template <typename T> inline T abs(const T a){return a>0?a:-a;} template <typename T> inline void swap(T&a,T&b){T c=a;a=b;b=c;} template <typename T> inline T gcd(const T a,const T b){if(!b)return a;return gcd(b,a%b);} template <typename T> inline T lcm(const T a,const T b){return a/gcd(a,b)*b;} template <typename T> inline T square(const T x){return x*x;}; template <typename T> inline void read(T&x) {char cu=getchar();x=0;bool fla=0;while(!isdigit(cu)){if(cu=='-')fla=1;cu=getchar();}while(isdigit(cu))x=x*10+cu-'0',cu=getchar();if(fla)x=-x; } template <typename T> inline void printe(const T x) {if(x>=10)printe(x/10);putchar(x%10+'0'); } template <typename T> inline void print(const T x) {if(x<0)putchar('-'),printe(-x);else printe(x); } LL EXgcd(const LL a,const LL b,LL &x,LL &y) { if(!b){x=1,y=0;return a; }const LL res=EXgcd(b,a%b,y,x);y-=a/b*x;return res; } inline LL msc(LL a,LL b,LL mod) {LL v=(a*b-(LL)((long double)a/mod*b+1e-8)*mod);return v<0?v+mod:v; } int n,a[11],p[11]; LL CRT() { LL P=1,sum=0; for(rg int i=1;i<=n;i++)P*=p[i];for(rg int i=1;i<=n;i++) {const LL m=P/p[i];LL x,y;EXgcd(p[i],m,x,y);sum=(sum+msc(msc(y,m,P),a[i],P))%P;}return sum; } int main() {read(n);for(rg int i=1;i<=n;i++)read(a[i]);for(rg int i=1;i<=n;i++){read(p[i]);a[i]=(a[i]%p[i]+p[i])%p[i]; }print(CRT());return flush(),0; }

擴展中國剩余定理(exCRT)

問題

給出nnn個同余方程
x≡a1(modp1)x≡a2(modp2)????????x≡an(modpn)\begin{aligned} x&amp;\equiv a_1\pmod{p_1}\\ x&amp;\equiv a_2\pmod{p_2}\\ ··&amp;\ \ \ \ \ ···\ \ \ \ \ \ \ \ ···\\ x&amp;\equiv a_n\pmod{p_n}\\ \end{aligned} xx??x?a1?(modp1?)a2?(modp2?)???????????????????an?(modpn?)?
求最小自然數解xxx
(與上面的問題的不同在于這里不保證所有的ppp兩兩互質)

做法

考慮我們現在已經符合了前k?1k-1k?1個限制了
P=lcm(p1,p2???pk?1)P=lcm(p_1,p_2···p_k-1)P=lcm(p1?,p2????pk??1),容易發現,滿足前k?1k-1k?1個限制的最小的自然數x&lt;Px&lt;Px<P
證明同理,也就是現在答案是x+tPx+tPx+tP形式的
我們要滿足第kkk個限制,其實很方便,就是找到一個ttt滿足
x+tP≡ak(modpk)x+tP\equiv a_k\pmod{p_k}x+tPak?(modpk?)
移項tP≡ak?x(modpk)tP\equiv a_k-x\pmod{p_k}tPak??x(modpk?)
轉化tP+qpk≡ak?xtP+qp_k\equiv a_k-xtP+qpk?ak??x
然后直接拓展歐幾里得求解
若無解輸出無解
否則直接將答案更新

例題

洛谷P4777 【模板】擴展中國剩余定理(EXCRT)
這道題保證有解,所以不用判無解了,保證了解的范圍,所以容易發現不用高精度

代碼

貼出ac代碼,代碼里有句注釋,是用來判無解的
為了卡常才把它注釋掉的

#include<cstdio> #include<cctype> #include<algorithm> namespace fast_IO {const int IN_LEN=10000000,OUT_LEN=10000000;char ibuf[IN_LEN],obuf[OUT_LEN],*ih=ibuf+IN_LEN,*oh=obuf,*lastin=ibuf+IN_LEN,*lastout=obuf+OUT_LEN-1;inline char getchar_(){return (ih==lastin)&&(lastin=(ih=ibuf)+fread(ibuf,1,IN_LEN,stdin),ih==lastin)?EOF:*ih++;}inline void putchar_(const char x){if(oh==lastout)fwrite(obuf,1,oh-obuf,stdout),oh=obuf;*oh++=x;}inline void flush(){fwrite(obuf,1,oh-obuf,stdout);} } using namespace fast_IO; #define getchar() getchar_() #define putchar(x) putchar_((x)) #define rg register typedef long long LL; template <typename T> inline T max(const T a,const T b){return a>b?a:b;} template <typename T> inline T min(const T a,const T b){return a<b?a:b;} template <typename T> inline void mind(T&a,const T b){a=a<b?a:b;} template <typename T> inline void maxd(T&a,const T b){a=a>b?a:b;} template <typename T> inline T abs(const T a){return a>0?a:-a;} template <typename T> inline void swap(T&a,T&b){T c=a;a=b;b=c;} template <typename T> inline T gcd(const T a,const T b){if(!b)return a;return gcd(b,a%b);} template <typename T> inline T lcm(const T a,const T b){return a/gcd(a,b)*b;} template <typename T> inline T square(const T x){return x*x;}; template <typename T> inline void read(T&x) {char cu=getchar();x=0;bool fla=0;while(!isdigit(cu)){if(cu=='-')fla=1;cu=getchar();}while(isdigit(cu))x=x*10+cu-'0',cu=getchar();if(fla)x=-x; } template <typename T> inline void printe(const T x) {if(x>=10)printe(x/10);putchar(x%10+'0'); } template <typename T> inline void print(const T x) {if(x<0)putchar('-'),printe(-x);else printe(x); } LL EXgcd(const LL a,const LL b,LL &x,LL &y) { if(!b){x=1,y=0;return a; }const LL res=EXgcd(b,a%b,y,x);y-=a/b*x;return res; } inline LL msc(LL a,LL b,LL mod) {LL v=(a*b-(LL)((long double)a/mod*b+1e-8)*mod);return v<0?v+mod:v; } LL n,a[100001],p[100001]; LL EXCRT() { LL P=1,sum=0; for(rg int i=1;i<=n;i++) {const LL o=((a[i]-sum)%p[i]+p[i])%p[i];//if(o%gcd(P,p[i])!=0)return -1;const LL xs=o/gcd(P,p[i]);LL x,y;EXgcd(p[i],P,x,y);const LL M=P;P=P/gcd(P,p[i])*p[i];sum=(sum+msc(msc(y,M,P),xs,P))%P;}return sum; }int main() {read(n);for(rg int i=1;i<=n;i++){read(p[i]),read(a[i]);a[i]=(a[i]%p[i]+p[i])%p[i];}print(EXCRT());return flush(),0; }

總結

并不是很難的兩個算法,學起來很方便
后記:感覺exCRT嚴格優于CRT,有沒有大佬指出CRT有什么用啊

超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生

總結

以上是生活随笔為你收集整理的中国剩余定理(CRT)扩展中国剩余定理(exCRT)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。