题意:给出n个模方程组:x mod ai = ri。求x的最小正值。如果不存在这样的x,那么输出-1.
涉及的数论知识:
对于一般式ax ≡ b(mod m)
当a=1时,两个同余方程就可以合并成一个同余方程
比如对于本题:
x mod a1=r1
x mod a2=r2
有不定方程:
x=r2+a2*y2
x=r2+a2*y2
联立:
a1y1+a2*(-y2)=r2-r1
可以通过扩展gcd求解出y1,回带解得特解(x*)
所以通解是满足合并后的同余方程的所有同余类解:x mod (lcm(a1,a2)) =(x*) (由数论结论知只有一类同余解,证明不说辣)
经过n-1次合并解出在0~lcm(a1,a2,a3...an)内的特解(x*) 就解决辣
//Accepted 148K 16MS C++ 989B
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
typedef long long ll;
using namespace std;
ll a1,r1,a2,r2;
ll x,y;
int n;
ll e_gcd(ll a,ll b,ll&x,ll&y)
{
ll ans;
if(b==0)
{
ans=a;
x=1,y=0;
}
else
{
ans=e_gcd(b,a%b,y,x);
y-=(a/b)*x;
}
return ans;
}
bool flag;
int main()
{
while(~scanf("%d",&n))
{
flag=0;
scanf("%I64d%I64d",&a1,&r1);
for(int i=1;i<n;i++)
{
scanf("%I64d%I64d",&a2,&r2);
ll R=r2-r1;
ll d=e_gcd(a1,a2,x,y);
ll tmp=a2/d;
if(R%d) flag=1;
r1=((x*R/d)%tmp+tmp)%tmp*a1+r1;//合并成新的同余方程
a1=a1*(a2/d);//合并成新的同余方程
}
if(flag) puts("-1");
else
{
ll lcm = a1;
ll ans=(r1%lcm+lcm)%lcm;//使解在0~lcm[a1,a2,a3...an]之内
printf("%I64d\n",ans);
}
}
return 0;
}