解题思路:这道题目因为不一定是互质的,所以直接套用中国剩余定理肯定是错的,,这里采用的是非互质的方法。。。之前的博客上面有详细的证明过程和算法,这里就不罗嗦了。。但是这道题目在输出的时候有特定的要求,要求是最小正整数,所以出现0的情况肯定是错的。如果出现0的情况,就取它们的最小公倍数即可。。
另外,多个数求最小公倍数的方法同样还是 a1*a2*a3*......*an / gcd(a1,a2,a3,......,an)。
AC:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
__int64 extend_gcd(__int64 a,__int64 b,__int64 &x,__int64 &y)
{
if(a == 0 && b == 0) return -1;
if(b == 0)
{
x = 1; y = 0;
return a;
}
__int64 d = extend_gcd(b,a%b,y,x);
y -= a/b*x;
return d;
}
__int64 gcd(__int64 a,__int64 b)
{
return b == 0 ? a : gcd(b,a%b);
}
void Chinese_Remainder(int m,int *a,int *b)
{
static int cas = 1;
__int64 n1,n2,b1,b2,flag = 0;
n1 = a[0]; b1 = b[0];
for(int i = 1; i < m; i++)
{
n2 = a[i]; b2 = b[i];
__int64 c = b2 - b1;
__int64 x,y,d;
d = extend_gcd(n1,n2,x,y);
if(c % d)
{
flag = 1;
break;
}
__int64 t = n2 / d;
x = (c /d * x % t + t) % t;
b1 = b1 + x * n1;
n1 = n1 / d * n2;
}
cout<<"Case "<<cas++<<": ";
if(flag)
cout<<-1<<endl;
else
{
if(b1 == 0 && m > 1)
{
b1 = a[0];
__int64 ans = 1;
for(int i = 1; i < m; i++)
b1 = gcd(a[i],b1);
for(int i = 0; i < m; i++)
ans *= a[i];
b1 = ans / b1;
}
else if(b1 == 0 && m == 1)
b1 = a[0];
cout<<b1<<endl;
}
}
int main()
{
int t,n,a[6],b[6];
cin>>t;
while(t--)
{
cin>>n;
for(int i = 0; i < n; i++)
cin>>a[i];
for(int i = 0; i < n; i++)
cin>>b[i];
Chinese_Remainder(n,a,b);
}
return 0;
}