中国剩余定理非互质版
中国剩余定理求解同余方程要求模数两两互质,在非互质的时候其实也可以计算,这里采用的是合并方程的思想。下面是详细推导。
#include<cstdio> #include<algorithm> #include<cmath> using namespace std; __int64 a[100000],b[1000000]; void ex_gcd(__int64 a,__int64 b,__int64 &d,__int64 &k1,__int64 &k2) { if(!b) k1=1,k2=0,d=a; else { ex_gcd(b,a%b,d,k2,k1); k2-=k1*(a/b); } } __int64 china(__int64 *a,__int64 *b,__int64 n) //互质版 { __int64 i; __int64 d,k1,k2,x=0,m,k=1; for(i=0;i<n;i++) k*=a[i]; for(i=0;i<n;i++) { m=k/a[i]; ex_gcd(a[i],m,d,k1,k2); x=(x+k2*m*b[i])%k; } return x>0?x:x+k; } __int64 ex_china(__int64 *a,__int64 *b,__int64 n) //非互质版 { __int64 x=a[0],y=b[0],k1,k2,d; for(int i=1;i<n;i++) { ex_gcd(x,a[i],d,k1,k2); if((b[i]-y)%d) return -1; k1=(b[i]-y)/d*k1%(a[i]/d); y+=k1*x; x=x/d*a[i]; y%=x; } return y>0?y:y+x; } int main() { __int64 n,i; while(~scanf("%I64d",&n)) { for(i=0;i<n;i++) scanf("%I64d%I64d",&a[i],&b[i]); printf("%I64d\n",ex_china(a,b,n)); } return 0; }