hdu 3579

蛋疼的一題啊,爲了這題先去學了中國剩餘定理(比較簡單),然後又去學了拓展歐幾里得,推了好久的公式,終於弄明白了,然後又去研究怎麼求解線性方程組,終於把這題過了。

拓展歐幾里得我就不講了,講一下這題怎麼解方程組的,網上只有代碼,沒有說明白怎麼推的。我們先可以先找兩個同餘方程 設通解爲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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章