题意:给出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; }
时间: 2024-11-10 05:58:33