hdu 2669 Romantic (扩展欧几里得)

来源:互联网 发布:zencart 建站 编辑:程序博客网 时间:2024/05/26 02:54

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2669

题意:求线性方程a*x + b*y = c的一组整数解,其中c=1,并要求x非负。

解题方案:扩展欧几里得。若gcd(a,b)!=1,则c不是gcd(a,b)的倍数,则无解。所以如果有解,则gcd(a,b)==1,即原方程可转换为a*x + b*y = gcd(a,b)。

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#include <vector>#include <queue>#include <stack>#include <set>#include <map>using namespace std;#define FOR(i,k,n) for(int i=k;i<n;i++)#define FORR(i,k,n) for(int i=k;i<=n;i++)#define scan(a) scanf("%d",&a)#define scann(a,b) scanf("%d%d",&a,&b)#define scannn(a,b,c) scanf("%d%d%d",&a,&b,&c)#define mst(a,n)  memset(a,n,sizeof(a))#define ll long long#define N 1005#define mod 1000000007#define INF 0x3f3f3f3fconst double eps=1e-8;const double pi=acos(-1.0);ll ex_gcd(ll a,ll b,ll &x,ll &y)//a*x+b*y=gcd(a,b){    if(b==0)    {        x=1; y=0;        return a;    }    ll d=ex_gcd(b,a%b,x,y);    ll xx=x;    x=y;    y=xx-a/b*y;    return d;}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    ll a,b;    while(cin>>a>>b)    {    ll x,y;        ll d=ex_gcd(a,b,x,y);        if(d==1)        {        while(x<0)//a(x+b)+b(y-a)=ax+by=1        {        x+=b;        y-=a;        }        printf("%lld %lld\n",x,y);        }        else            printf("sorry\n");    }    return 0;}

将取x非负解的时候的复杂度降到O(1),参考代码:扩展欧几里得算法详解

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#include <vector>#include <queue>#include <stack>#include <set>#include <map>using namespace std;#define FOR(i,k,n) for(int i=k;i<n;i++)#define FORR(i,k,n) for(int i=k;i<=n;i++)#define scan(a) scanf("%d",&a)#define scann(a,b) scanf("%d%d",&a,&b)#define scannn(a,b,c) scanf("%d%d%d",&a,&b,&c)#define mst(a,n)  memset(a,n,sizeof(a))#define ll long long#define N 1005#define mod 1000000007#define INF 0x3f3f3f3fconst double eps=1e-8;const double pi=acos(-1.0);ll ex_gcd(ll a,ll b,ll &x,ll &y)//a*x+b*y=gcd(a,b){    if(b==0)    {        x=1; y=0;        return a;    }    ll d=ex_gcd(b,a%b,x,y);    ll xx=x;    x=y;    y=xx-a/b*y;    return d;}ll cal(ll a,ll b,ll c)//a*x+b*y=c中x的最小正整数解{    ll x,y;    ll gcd=ex_gcd(a,b,x,y);//得到a*x+b*y=gcd(a,b)的解     if(c%gcd!=0) return -1;    x*=c/gcd;//得到a*x+b*y=c①的解x     b/=gcd;//为得到x的最小正整数解,将方程①化为等价的a'*x+b'*y=c'②(等式两边同除以gcd),解不变 //在本题中这句可以去掉,本题只要求x非负即可    if(b<0) b=-b;//为取模方便,当b为负数时,将方程②化为等价的a''*x+b''*y=c''③(等式两边同乘以-1),解不变 //在本题中这句可以去掉,本题b>0    ll ans=x%b;//当x>0时,此时直接取到x的最小正整数解;当x<=0时,对b取模后再加b可得x的最小正整数解    if(ans<=0) ans+=b;    return ans;}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    ll a,b;    while(cin>>a>>b)    {        ll ans=cal(a,b,1);        if(ans!=-1)            printf("%lld %lld\n",ans,(1-a*ans)/b);        else            printf("sorry\n");    }    return 0;}



0 0
原创粉丝点击