前置知识:扩展欧几里得、裴蜀定理、求解线性同余方程;
题意:解同余方程组 模数不互质...
解线性同余方程用exgcd 比如解 ax≡c(mod b)
也就是 ax+by=c,
exgcd可以解出 ax+by=gcd(a,b) ,
变一下? 方程同乘一个c/gcd(a,b)也就是 a*(x*c/gcd)+b(y*c/gcd)=c
所以exgcd解出x再乘一个c/gcd(a,b)就是一组可行解
解同余方程组 已知前i-1项通解 x0+k*LCM k∈Z ,
引入第i项时 求出一个最小的t满足 x0+t*LCM ≡ ai(mod mi) 此时x=x0+t*LCM 就是答案....
有些题还要用裴蜀定理判无解 这道不用 看代码...
// 已知前i-1项通解 x0+k*LCM k∈Z //引入第i项时 求出一个最小的t满足 x0+t*LCM ≡ ai(mod mi) 此时x=x0+t*LCM // 移向 t*LCM ≡ ai-x0 (mod mi) // 扩欧 求 即可 // ax≡c(mod b) exgcd算出 ax≡1(mod b) x再乘上c/gcd(a,b)即可 c%gcd(a,b)!=0时无解 #include<bits/stdc++.h> #define int long long using namespace std; typedef long long lt; int x,y; int n,ai[100000],bi[100000]; int mul(int a,int b, int p){ int res=0; while(b){ if(b&1){ res=(res+a)%p; } a=(a+a)%p; b>>=1; } return res; }//龟速乘 int exgcd(int a,int b,int &x,int &y){ if(b==0){ x=1; y=0; return a; } int d=exgcd(b,a%b,x,y); int t=x; x=y; y=t-(a/b)*y; return d; }//扩欧 int excrt(){ int ans=ai[1],M=bi[1]; for(int i=2;i<=n;i++){ int a=M,b=bi[i],c=(ai[i]-ans%b+b)%b;//a ≡c(mod b) int gcd=exgcd(a,b,x,y),bg=b/gcd;//算t*LCM ≡ gcd(mod mi) if(c%gcd!=0)return -1;//无解情况 x=mul(x,c/gcd,bg);//t*LCM ≡ ai-x0 (mod mi) 先算 t*LCM ≡ gcd (mod mi) 答案再乘上 (ai-x0)/gcd即为t ans+=x*M; //答案 M*=bg;//更新LCM ans=(ans%M+M)%M; //%M是因为 x=x0+t*M 写成同余方程即为 x ≡ x0(mod M)%M不影响答案正确性 } return (ans%M+M)%M; }//扩展中国剩余定理 signed main(){ scanf("%lld",&n); for(int i=1;i<=n;i++){ scanf("%lld%lld",&bi[i],&ai[i]); } printf("%lld",excrt()); }