[数论] 同余方程组 poj2891 Strange Way to Express Integers

来源:互联网 发布:foreach遍历数组详解 编辑:程序博客网 时间:2024/05/29 08:01

poj2891 Strange Way to Express Integers:http://poj.org/problem?id=2891

其实应该是这样的:
P=b1(mod a1); (P%a1=b1)
P =b2(mod a2);
P =b3(mod a3);
……
P =bn(mod an);
给出a,b 求P

解:
第一条:a1*x+b1= P
第二条:a2*y+b2= P
第一条减去第二条: a1*x - a2*y = b2-b1
设A=a1,B=-a2,K=b2-b1,得到了A*x+B*y=K 标准同余方程
利用exgcd就可得解
(实际调用exgcd的时候不理会a2前面的负号)

如果K%d!=0,无解
否则,X=[ (x* K/d)%(B/d)+(B/d) ]%(B/d)

(LCU表示最小公倍数)
P= a1*X+b1+ 若干倍的LCU(a1,a2)
(或者把Y=(K-AX)/B,再P=a2*Y+b2+ 若干倍的LCU(a1,a2))
所以新的b= a1*x+b1,新的a= LCU(a1,a2),
把新的b当成b1,新的a当成a1,再去和a3和b3结合,一直到最后结束,最后的b就是X

同余方程(拓展欧几里得算法):http://blog.csdn.net/qq_36038511/article/details/76887494

代码~~

#include <cstdio>#include <cstring>using namespace std;typedef long long LL;void exgcd(LL a,LL b,LL &d,LL &x,LL &y){    if (a==0)    {        x=0;y=1;        d=b;    }    else    {        LL tx,ty;        exgcd(b%a,a,d,tx,ty);        x=ty-(b/a)*tx;        y=tx;    }}int main(){    LL a,b,d,x,y,b1,b2,m1,m2,A,B,K;    int n;    while (scanf("%d",&n)!=EOF)    {        bool u=true;        scanf("%lld%lld",&m1,&b1);        for (int i=2;i<=n;i++)        {            scanf("%lld%lld",&m2,&b2);            A=m1;B=m2;K=b2-b1;            exgcd(A,B,d,x,y);            if (K%d!=0) u=false;            x=((x*(K/d)%(B/d))+(B/d))%(B/d);            b1=x*m1+b1;            m1=m1*m2/d;        }        if (u==false) printf("-1\n");        else printf("%lld\n",b1);    }    return 0;}
阅读全文
0 0
原创粉丝点击