首页 > 技术文章 > 【poj2891-Strange Way to Express Integers】拓展欧几里得-同余方程组

KonjakJuruo 2016-02-02 20:56 原文

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

题意:与中国剩余定理不同,p%ai=bi,此处的ai(i=1 2 3 ……)是不一定互质的,所以要用到的是同余方程组,在网上看到有人称为拓展中国剩余定理。

具体讲解可以看我昨天的博文:http://www.cnblogs.com/KonjakJuruo/p/5176417.html

//poj2891
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;

typedef long long LL;
const LL N=11000;
LL a[N],b[N];
LL tx,ty;

LL exgcd(LL aa,LL bb)
{
    if(bb==0) {tx=1,ty=0;return aa;}
    LL d=exgcd(bb,aa%bb);
    LL x=ty,y=tx-(aa/bb)*ty;
    tx=x;ty=y;
    return d;
}

LL lcu(LL aa,LL bb)
{
    LL d=exgcd(aa,bb);
    return aa*bb/d;
}

int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    // printf("%d\n",(-5)%3);
    LL n,a1,b1,x;
    while(scanf("%I64d",&n)!=EOF)
    {
        bool bk=1;
        for(LL i=1;i<=n;i++)
            scanf("%I64d%I64d",&a[i],&b[i]);
        LL A=a[1],B=a[2],C=b[2]-b[1];
        LL g=exgcd(A,B);
        if(C%g) bk=0; 
        else {
            x=((tx*C/g)%(B/g)+(B/g))%(B/g);
            b1=a[1]*x+b[1];
            a1=lcu(a[1],a[2]);
        }
        for(LL i=3;i<=n;i++)
        {
            A=a1,B=a[i],C=b[i]-b1;
            g=exgcd(A,B);
            if(C%g) {bk=0;break;}
            x=((tx*C/g)%(B/g)+(B/g))%(B/g);
            b1=a1*x+b1;
            a1=lcu(a1,a[i]);
        }
        if(bk)    printf("%I64d\n",b1);
        else printf("-1\n");
    }
    return 0;
}
View Code

 

推荐阅读