此处省略引经据典。
(为了方便叙述,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)的最小正整数解。
考虑转化为三个子问题。
思考后可得 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)
(显然,对于互质的u,v,可以得到x=(0,0)(u,v)=u*v。因此,(1,0,0)(3,5,7)=(1,0)(3,35)=3-1(mod 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*m1-1(modM/m1)+……an*mn-1(modM/mn))
而关于逆元,可以也只可以用扩展欧几里得来求(扩展欧几里得求逆元可以参考小蒟蒻的这篇博客)。
细节见代码。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int sz=1e5+5; 4 int n,a[sz],m[sz],M,x,y,ans; 5 void exgcd(int a,int b,int &x,int &y){ 6 if(b==0){ 7 x=0; 8 y=1; 9 return ; 10 } 11 exgcd(b,a%b,y,x); 12 y-=x*(a/b); 13 } 14 int main(){ 15 scanf("%d",&n); 16 M=1; 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[i],M/m[i],x,y); 21 ans+=a[i]*x; 22 ans=(ans%M+M)%M; 23 } 24 printf("%d",ans); 25 return 0; 26 }