若有以下两个同余方程
x ≡ a1 mod n1
x ≡ a2 mod n2
x= n1*k1+a1 = n2*k2+a2
∴ n1*k1 = n2*k2+a2-a1
∴ n1*k1 ≡ a2-a1 mod n2
由扩展欧几里得定理得,同余方程有解的条件是 gcd(n1,n2) | (a2-a1)
令d=gcd(n1,n2),c=a2-a1
则n1/d * k1 ≡ c/d mod n2/d
∴ k1 = c/d * inv(n1/d)mod n2/d
令k=c/d * inv(n1/d),则k1 = k + (n2/d)*y
∴ x=n1*(k + (n2/d)*y)+a1
=(n1*n2/d)*y+n1*k+a1
即 x ≡ n1*k+a1 mod n1*n2/d
所以上面两个方程合并为 x ≡ a mod n
其中 a=n1*k+a1 n=n1*n2/d
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long LL;
int n[11],a[11];
void read(int &x)
{
x=0; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
}
int gcd(LL a,LL b,LL &x,LL &y)
{
if(!b) { x=1; y=0; return a;}
LL g=gcd(b,a%b,y,x); y-=a/b*x;
return g;
}
int main()
{
int T,m;
read(T);
LL a1,n1,a2,n2;
LL d,c,k;
LL x,y;
while(T--)
{
read(m);
for(int i=1;i<=m;++i) read(n[i]);
for(int i=1;i<=m;++i) read(a[i]);
bool tag=true;
a1=a[1],n1=n[1];
for(int i=2;i<=m;++i)
{
a2=a[i]; n2=n[i];
d=gcd(n1,n2,x,y);
c=a2-a1;
if(c%d) { tag=false; break; }
gcd(n1/d,n2/d,x,y);
k=(x*c/d%(n2/d)+n2/d)%(n2/d);
a1=(a1+n1*k)%(n1/d*n2);
n1=n1/d*n2;
}
if(!tag) printf("No solution\n");
else printf("%I64d\n",a1);
}
}
来源:https://www.cnblogs.com/TheRoadToTheGold/p/8458326.html