Description
给出n个模方程组:x mod ai = ri。求x的最小正值。如果不存在这样的x,那么输出-1
Input
多组输入,每组用例第一行为方程组方程个数n,之后n行每行两个整数ai和ri分别被表示模数和余数,以文件尾结束输入
Output
对于每组用例,输出最小的正值x,如果不存在则输出-1
Sample Input
2
8 7
11 9
Sample Output
31
Solution
因为此处模数不互素所以不能直接采用中国剩余定理来解决,只能两两来求,例如X mod a1 = r1,X mod a2 = r2,两方程联立得到a1*x+a2*y=r2-r1,通过解一元线性同余方程得到x后令r1=x,a1=lcm(a1,a2),然后再解X mod a1 = r1,X mod a3 = r3……以此类推即可
Code
#include<cstdio>
#include<iostream>
using namespace std;
#define maxn 1111
#define INF 0x3f3f3f3f
typedef long long ll;
ll extend_gcd(ll a,ll b,ll & x,ll & y)//扩展欧几里得,求解ax+by=gcd(a,b)
{
ll d=a;
if(b!=0)
{
d=extend_gcd(b,a%b,y,x);
y-=(a/b)*x;
}
else
{
x=1;
y=0;
}
return d;
}
ll n;
int main()
{
while(~scanf("%lld",&n))
{
ll a1,r1;
int flag=1;
scanf("%lld%lld",&a1,&r1);
for(int i=1;i<n;i++)
{
ll a2,r2;
scanf("%lld%lld",&a2,&r2);
ll x,y;
ll a=a1,b=r2-r1,c=a2;
ll g=extend_gcd(a,c,x,y);
if(b%g)//无解
{
flag=0;
continue;
}
ll mod=c/g;
x=x*(b/g);
x=(x%mod+mod)%mod;
r1=x*a1+r1;
a1=a1*a2/g;
r1=(r1%a1+a1)%a1;
}
if(flag)
printf("%lld\n",r1);
else
printf("-1\n");
}
return 0;
}