POJ 2891 Strange Way to Express Integers 扩展gcd

来源:互联网 发布:于正 知乎 编辑:程序博客网 时间:2024/06/02 03:14

题意:

求一个最小的数使得这个数对ai取余为bi如果不存在则输出-1

首先讨论只有2组数的情况 设这个要求的数为 m 那么有 a1*x+b1=a2*y+b2=m

可以转化为 a1*x-a2*y=b2-b1

那么可以套用ex_gcd求出一个通解x0 x0=(x0*(b2-b1)/gcd(a1,a2)%t+t)%t 保证是最小正解 t=a2/gcd(a1,a2);

当然如果(b2-b1)%gcd(a1,a2)不为0的话不存在这样的解,这时候就输出-1

现在求出只有2组数据的情况的解 那么怎么才能扩展到n组解呢?

我们可以把求出的对于这2组数据的解稍微处理下加入待处理数据即可

怎么处理?让a1=lcm(a1,a2) b1=a1*x0+b1 这样可以保证求出新的解能满足前两组数据的要求

ACcode:

#include <iostream>#include <cstdio>#define ll long longusing namespace std;ll ex_gcd(ll a,ll b, ll &x,ll & y){    if(a==0&&b==0)return -1;    if(b==0){x=1,y=0;return a;}    ll d=ex_gcd(b,a%b,y,x);    y-=a/b*x;    return d;}int main(){    ll n,a1,b1,a2,b2,x,y,a,b,c,d;    while(cin>>n){        cin>>a1>>b1;        bool flag=true;        for(int i=1;i<n;++i){            cin>>a2>>b2;            a=a1,b=a2,c=b2-b1;            d=ex_gcd(a,b,x,y);            if(c%d){                flag=false;                continue;            }            ll t=b/d;            x=(x*(c/d)%t+t)%t;            b1=a1*x+b1;            a1=a1*(a2/d);///a1= lcm(a1,a2)        }        if(flag)printf("%I64d\n",b1);        else printf("-1\n");    }    return 0;}


0 0
原创粉丝点击