https://blog.csdn.net/niiick/article/details/80229217
拓展中国剩余定理
注意拓展欧几里得只能解出a,b,x,y,gcd(a,b)的一组特解
模板1
long long exgcd(long long a, long long b, long long &x, long long &y) {//比较好的exgcd() if (!b) {x = 1; y = 0; return a;} long long d = exgcd(b, a % b, y, x); y -= a / b * x; return d; }
int china() { int ans=0,lcm=1,x,y; for(int i=1;i<=k;++i) lcm*=b[i]; for(int i=1;i<=k;++i) { int tp=lcm/b[i]; exgcd(tp,b[i],x,y); x=(x%b[i]+b[i])%b[i];//x要为最小非负整数解 ans=(ans+tp*x*a[i])%lcm; } return (ans+lcm)%lcm; }
模板2:拓展定理
/* 拓展中国剩余定理,不互质的模数 */ #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; #define ll long long #define maxn 100005 int n; ll m[maxn],a[maxn];//模数,余数 //拓展欧几里得,解出ax+by=gcd(a,b)的特解 ll exgcd(ll a,ll b,ll &x,ll &y){ if(b==0){x=1;y=0;return a;} ll d=exgcd(b,a%b,y,x); y-=a/b*x; return d; } ll excrt(){//x % mi = ai 方程组 ll M=m[1],A=a[1],x,y;//M=lcm(m1,m2...),A= for(int i=2;i<=n;i++){ ll d=exgcd(M,m[i],x,y); ll c=a[i]-A; if(c%d)return -1;//d不能整除c,即gcd(M,m[i])不能整除 a[i]-A ll mul=m[i]/d;//mi/gcd(M,mi) ll u=(c/d*x%mul+mul)%mul;//当前两个方程组联立的通解u,注意要最小整数解 A=A+M*u;//下一轮的A M=M*mul;//下一轮的M A%=M; } return (A+M)%M; } int main(){ while(cin>>n){ for(int i=1;i<=n;i++) cin>>m[i]>>a[i]; ll ans=excrt(); cout<<ans<<endl; } }