poj 2891 Strange Way to Express Integers (解模線性方程組)
阿新 • • 發佈:2019-02-14
題意:有一個數x,給定k組ai和ri,使得x%ai=ri
求x最小為多少
分析:求解模線性方程組
x = a1(mod m1)
x = a2(mod m2)
x = a3(mod m3)
先求解方程組前兩項。 x=m1*k1+a1=m2*k2+a2
-> m1*k1+m2*(-k2)=a2-a1
這個方程可以通過歐幾里得求解出最小正整數的k1 則x=m1*k1+a1 顯然x為兩個方程的最小正整數解。
則這兩個方程的通解為 X=x+k*LCM(m1,m2) -> X=x(mod LCM(m1,m2)) 就轉換成了一個形式相同方程了
在通過這個方程和後面的其他方程求解。最終的結果就出來了。
#include<stdio.h> __int64 exgcd(__int64 a,__int64 b,__int64 &x,__int64 &y) //擴充套件歐幾里得 { __int64 t,d; if(b==0){ x=1; y=0; return a; } d=exgcd(b,a%b,x,y); t=x; x=y; y=t-a/b*y; return d; } int main() { __int64 a1,a2,r1,r2,c,d,x,y; int k,i,flag; while(scanf("%d",&k)!=EOF){ scanf("%I64d%I64d",&a1,&r1); flag=1; for(i=1;i<k;i++){ scanf("%I64d%I64d",&a2,&r2); if(!flag) continue; d=exgcd(a1,a2,x,y); c=r2-r1; if(c%d) flag=0; else{ x*=c/d; x=(x%(a2/d)+a2/d)%(a2/d); //最小正解 r1=a1*x+r1; a1=a1*a2/d; //最小公倍數 } } if(flag) printf("%I64d\n",r1); else printf("-1\n"); } return 0; }