参考文章地址: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);
}
}