蛋疼的一題啊,爲了這題先去學了中國剩餘定理(比較簡單),然後又去學了拓展歐幾里得,推了好久的公式,終於弄明白了,然後又去研究怎麼求解線性方程組,終於把這題過了。
拓展歐幾里得我就不講了,講一下這題怎麼解方程組的,網上只有代碼,沒有說明白怎麼推的。我們先可以先找兩個同餘方程 設通解爲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;
}