poj 2891 Strange Way to Express Integers(中国剩余定理)

http://poj.org/problem?id=2891


题意:求解一个数x使得 x%8 = 7,x%11 = 9;    若x存在,输出最小整数解,否则输出-1; 
 
ps:
思路:这不是简单的中国剩余定理问题,因为输入的ai不一定两两互质,而中国剩余定理的条件是除数两两互质;    这是一般的模线性方程组,对于     X mod m1=r1     X mod m2=r2     ...     ...     ...     X mod mn=rn 首先,我们看两个式子的情况 X mod m1=r1……………………………………………………………(1) X mod m2=r2……………………………………………………………(2) 则有  X=m1*k1+r1………………………………………………………………(*) X=m2*k2+r2 那么 m1*k1+r1=m2*k2+r2 整理,得 m1*k1-m2*k2=r2-r1 令(a,b,x,y,m)=(m1,m2,k1,k2,r2-r1),原式变成 ax+by=m 熟悉吧? 此时,因为GCD(a,b)=1不一定成立,GCD(a,b) | m 也就不一定成立。所以应该先判 若 GCD(a,b) | m 不成立,则!!!方程无解!!!。 否则,继续往下。 解出(x,y),将k1=x反代回(*),得到X。 于是X就是这两个方程的一个特解,通解就是 X'=X+k*LCM(m1,m2) 这个式子再一变形,得 X' mod LCM(m1,m2)=X 这个方程一出来,说明我们实现了(1)(2)两个方程的合并。 令 M=LCM(m1,m2),R=r2-r1 就可将合并后的方程记为 X mod M = R。 然后,扩展到n个方程。 用合并后的方程再来和其他的方程按这样的方式进行合并,最后就能只剩下一个方程 X mod M=R,其中 M=LCM(m1,m2,...,mn)。 那么,X便是原模线性方程组的一个特解,通解为 X'=X+k*M。 如果,要得到X的最小正整数解,就还是原来那个方法: X%=M; if (X<0) X+=M; 

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#define LL long long
#define _LL __int64
#define eps 1e-8

using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 10;

_LL k;
_LL M;

_LL extend_gcd(_LL a,_LL b,_LL &x,_LL &y)
{
    if(b == 0)
    {
        x = 1;
        y = 0;
        return a;
    }
    else
    {
        _LL r = extend_gcd(b,a%b,x,y);
        _LL t = x;
        x = y;
        y = t-a/b*y;
        return r;
    }
}

int main()
{
    _LL a1,m1,a2,m2,x,y,i,d;
    while(scanf("%lld",&k)!= EOF)
    {
        bool flag = true;
        scanf("%lld %lld",&m1,&a1);
        for(i = 1; i < k; i++)
        {
            scanf("%lld %lld",&m2,&a2);

            d = extend_gcd(m1,m2,x,y);

            if((a2-a1)%d != 0)
                flag = false;

            _LL t = m2/d;
            x *= (a2-a1)/d;
            x = (x%t + t)%t;
            //注意新的m1,a1是怎么得来的
            a1 = x*m1+a1;
            m1 = m1*m2/d;
            a1 = (a1%m1+m1)%m1;
        }
        if(flag == true)
            printf("%lld\n",a1);
        else printf("-1\n");

    }
    return 0;
}


你可能感兴趣的:(中国剩余定理,模线性方程组)