首页 > 代码库 > poj 2891 Strange Way to Express Integers (解模线性方程组)

poj 2891 Strange Way to Express Integers (解模线性方程组)

链接:poj 2891

题意:有一个数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;
}



poj 2891 Strange Way to Express Integers (解模线性方程组)