您的位置:首页 > 其它

POJ 2891 Strange Way to Express Integers 扩展gcd

2016-08-01 11:49 344 查看
题意:

求一个最小的数使得这个数对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 long
using 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: