* 让我们来改变一下格式:
• x+y1a1=b1① • x-y2a2=b2② • x-y3a3=b3③ • …
①②相减得:
• y1a1+y2a2=b1-b2
用exgcd求解,不能解就无解。然后我们可以解出一个最小正整数y1,带入①得到x其中一个解:
• x0=b1-y1a1
它的全解为x=x0+k*lcm(a1,a2)(由y1的全解可导)即x=x0(mod lcm(a1,a2)), 则:
• x+y3*lcm(a1,a2)=x0④
③④再联立,重复以上过程即可。
excrt部分的代码如下:
1 void excrt() { 2 for(int i = 2; i <= n; i++) { 3 A = m[1], B = m[i], C = a[i]-a[1]; 4 C = (C%B+B)%B; 5 int g = exgcd(A,B,x,y); 6 x = x*(C/g); 7 x = (x%B+B)%B; 8 a[1] = a[1]+ m[1]*x; 9 m[1] = m[1]*(m[i]/g); 10 a[1] = (a[1]%m[1]+m[1])%m[1]; 11 } 12 }
完整代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #define int long long 6 using namespace std; 7 const int maxn = 1e6; 8 int n,x,y,A,B,C; 9 int m[maxn],a[maxn],ans; 10 int qm(int a,int b,int mo){ 11 int ans = 0,base = a; 12 while(b){ 13 if(b&1) ans = (ans+base) %mo; 14 base = (base+base) %mo; 15 b >>= 1; 16 } 17 return ans; 18 } 19 int exgcd(int a,int b,int &x,int &y) { 20 if(!b) { 21 x=1, y=0; 22 return a; 23 } 24 int g = exgcd(b,a%b,x,y); 25 int tx = x; 26 x = y; 27 y = tx-(a/b)*y; 28 return g; 29 } 30 void excrt() { 31 for(int i = 2; i <= n; i++) { 32 A = m[1], B = m[i], C = a[i]-a[1]; 33 C = (C%B+B)%B; 34 int g = exgcd(A,B,x,y); 35 x = qm(x,(C/g),B); 36 x = (x%B+B)%B; 37 a[1] = a[1]+ qm(m[1],x,m[1]*(m[i]/g)); 38 m[1] = m[1]*(m[i]/g); 39 a[1] = (a[1]%m[1]+m[1])%m[1]; 40 } 41 } 42 main() { 43 scanf("%lld",&n); 44 for(int i = 1; i <= n; i++) 45 scanf("%lld%lld",&m[i],&a[i]); 46 excrt(); 47 printf("%lld",a[1]); 48 }