中国剩余定理模板+理解 推导

此处省略引经据典。

(为了方便叙述,x=(a1,a2,a3)(b1,b2,b3)表示  x≡a1(mod b1)  x≡a2(mod b2) x≡a3(mod b3) )

举个栗子。

栗子 求x=(2,3,2)(3,5,7)的最小正整数解。

考虑转化为三个子问题。

(显然,对于互质的u,v,可以得到x=(0,0)(u,v)=u*v。因此,(1,0,0)(3,5,7)=(1,0)(3,5*7)=35*(35-1(mod 3))%3)

思考后可得 x=(2*(1,0,0)(3,5,7)+3*(0,1,0)(3,5,7)+2*(0,0,1)(3,5,7))(mod 3*5*7)

推而广之,考虑n个两两互质的数 m1,m2,m3,……mn-1,mn,设他们的积为M。

则,x=(a1,a2,a3,……an)(m1,m2,m3,……mn)=(a1*(1,0,……,0)+a2*(0,1,0,……,0)+……an*(0……0,1))=

(a1*(M/m1)*((M/m1)-1(mod m1)%m1)+……an*(M/mn)*((M/mn)-1(mod mn)%mn))

而关于逆元,可以用扩展欧几里得来求(扩展欧几里得求逆元可以参考小蒟蒻的这篇博客,貌似快速幂求逆元也适用?)。

细节见代码。

 1 #include <cstdio>
 2 using namespace std;
 3 int x,y,M=1;
 4 void exgcd(int aa,int bb,int &x,int &y){
 5     if(bb==0){
 6         x=1;
 7         y=0;
 8         return ;
 9     }
10     exgcd(bb,aa%bb,y,x);
11     y-=x*(aa/bb); 
12 } 
13 const int sz=1e5+5;
14 int a[sz],m[sz],ans,n;
15 int main(){
16     scanf("%d",&n);
17     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
18     for(int i=1;i<=n;i++)scanf("%d",&m[i]),M*=m[i];
19     for(int i=1;i<=n;i++){
20         exgcd(M/m[i],m[i],x,y);
21         x=(x%m[i]+m[i])%m[i];
22         ans+=a[i]*x*(M/m[i]);
23         ans=(ans%M+M)%M;
24     }
25     printf("%d",ans); 
26     return 0;
27 }

引用一个POJ的模板题 POJ1006

该题代码如下

 1 #include <cstdio>
 2 using namespace std;
 3 int x,y;
 4 const int M=21252;
 5 void exgcd(int aa,int bb,int &x,int &y){
 6     if(bb==0){
 7         x=1;
 8         y=0;
 9         return ;
10     }
11     exgcd(bb,aa%bb,y,x);
12     y-=x*(aa/bb); 
13 } 
14 int t,a[3],m[3]={23,28,33},d,ans;
15 int main(){
16     for(t=1;;++t){
17         ans=0;
18         for(int i=0;i<3;i++){
19             scanf("%d",&a[i]);
20             exgcd(M/m[i],m[i],x,y);
21             x=(x%m[i]+m[i])%m[i];
22             ans+=a[i]*x*(M/m[i]);
23             ans=(ans%M+M)%M;
24         }
25         scanf("%d",&d);
26         if(d==-1)break;
27         ans-=d;
28         ans=(ans%M+M)%M;
29         if(ans==0)ans=M;
30         printf("Case %d: the next triple peak occurs in %d days.
",t,ans); 
31     }
32     return 0;
33 }
原文地址:https://www.cnblogs.com/BLeaves/p/8651995.html