蛋疼的一题啊,为了这题先去学了中国剩余定理(比较简单),然后又去学了拓展欧几里得,推了好久的公式,终于弄明白了,然后又去研究怎么求解线性方程组,终于把这题过了。
拓展欧几里得我就不讲了,讲一下这题怎么解方程组的,网上只有代码,没有说明白怎么推的。我们先可以先找两个同余方程 设通解为N,N=r1(mod(m1)),N=r2(mod(m2)),显然可以化为k1*m1+r1=k2*m2+r2;--->k1*m1+(-k2*m2)=r2-r1;设a=m1,b=m2,x=k1,y=(-k2),c=r2-r1方程可写为ax+by=c;由欧几里得解得x即可,那么将x化为原方程的最小正整数解,(x*(c/d)%(b/d)+(b/d))%(b/d);这里看不懂的去看解模线性方程。那么这个x就是原方程的最小整数解。所以N=a*(x+n*(b/d))+r1====N=(a*b/d)*n+(a*x+r1),这里只有n为未知数所以又是一个N=(a*x+r1)(mod(a*b/d))的式子,然后只要不断的将两个式变成一个式子,最后就能解出这个方程组的解。
Run ID | Submit Time | Judge Status | Pro.ID | Exe.Time | Exe.Memory | Code Len. | Language | Author |
5296255 | 2012-01-26 17:12:50 | Accepted | 3579 | 0MS | 316K | 1055 B | G++ | xym2010 |
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
#define LL long long
using namespace std;
const int size=100005,MAX=1<<30,MIN=-(1<<30);
LL m[10],r[10];
void ex_gcd(LL a,LL b,LL &d,LL &x,LL &y)
{
if(b==0)
{
x=1,y=0,d=a;
}
else
{
ex_gcd(b,a%b,d,y,x);
y-=x*(a/b);
}
}
LL gcd(LL a,LL b)
{
return b==0?a:gcd(b,a%b);
}
LL china_remain(int n)
{
LL a,b,c,c1,c2,x,y,d,N;
a=m[0];c1=r[0];
for(int i=1;i<n;i++)
{
b=m[i];c2=r[i];
ex_gcd(a,b,d,x,y);
c=c2-c1;
if(c%d)return -1;
LL b1=b/d;
x=((c/d*x)%b1+b1)%b1;
c1=a*x+c1;
a=a*b1;
}
if(c1==0)//当余数都为0
{
c1=1;
for(int i=0;i<n;i++)
c1=c1*m[i]/gcd(c1,m[i]);
}
return c1;
}
int main()
{
int T,n;
scanf("%d",&T);
for(int t=1;t<=T;t++)
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%lld",&m[i]);
for(int i=0;i<n;i++)
scanf("%lld",&r[i]);
cout<<"Case "<<t<<": "<<china_remain(n)<<endl;
}
return 0;
}