參考文章地址:http://blog.csdn.net/hqd_acm/article/details/6173859
題目:http://poj.org/problem?id=2891
思路:
x=r1 (mod a1) x=r2 (mod a2)--->a1*x+a2*y=gcd(a1,a2)=d--->r1+a1*x=r2+a2*y ---> a1*x+a2*y=r2-r1 (1)則(r2-r1)%d!=0,方程(1)的解不存在。否則{ t=a2/d; x=((x*(r2-r1)/d)%t+t)%t//x的最小整數解 r1=x*a1+r1 //求出原方程X=a1*x+r1 a1=a1*a2/d; r1=(r1%a1+a1)%a1; //r1<a1}思想就是要將兩個方程式合并,合并式X=a3x+r3,既要mod a1=r1,而且要mod a2=r2,所以有a3是a1與a2的最小公倍數,r3是方程a1*x+a2*y=r2-r1的解。
原始碼:
#include <stdio.h>typedef long long ll;ll n,a[100000],r[100000];ll extend_gcd(ll a,ll b,ll &x,ll &y){ ll t,ans; if(b==0) { x=1; y=0; return a ;} else { ans=extend_gcd(b,a%b,x,y); t=x; x=y; y=t-a/b*y; } return ans;}void solve(ll a[],ll r[],ll n){ ll a1,a2,r1,r2,x,y,d,t; int flag; a1=a[0]; r1=r[0]; if(n==1) { if(a1<=r1) printf("-1\n"); // else printf("%lld\n",r1); return; } flag=1; for(int i=1;i<n;i++) { a2=a[i]; r2=r[i]; if(a2<=r2) { printf("-1\n"); flag=0; break; } d=extend_gcd(a1,a2,x,y); if((r2-r1)%d!=0) { printf("-1\n"); flag=0; break; } else { t=a2/d; x=(x*(r2-r1)/d%t+t)%t; r1=a1*x+r1; a1=a1*a2/d; r1=(r1%a1+a1)%a1; } } if(flag) printf("%lld\n",r1);}int main(){ while(scanf("%lld",&n)!=EOF) { for(int i=0;i<n;i++) scanf("%lld %lld",&a[i],&r[i]); solve(a,r,n); }}