数学(扩展欧几里得算法)经典模板

来源:互联网 发布:复杂sql语句优化 编辑:程序博客网 时间:2024/04/28 13:47

poj2142原题链接


这道题大概题意就是说已经给出了a,b,c,然后分别求出ax+by=c里边的x,y,注意这里可能就是ax-by=c或者by-ax=c两种情况,如果要分这几种情况讨论的话,卫冕会有些复杂,但是我们又该怎么去解决的呢?

我有种思路,直接就是使用直接判断abs(X)+abs(Y)<ans,如果满足条件,就直接赋值。当然如果不满足,那么直接就不管他了。

当然最后输出的时候也是需要讨论的,因为可能得到的abs(X)和abs(Y)不知道谁大鞋,所以在这里就用了个小技巧,在前边输入的时候判断一下,是不是a<b,如果是那么记录下,并且把a和b互换一下,以便后边的输出,所以在最后就直接判断前边的a和b是不是已经被互换了,如果被互换了,那么就要反着输出来,也就是说在计算里边的a和b已经互换身份了,所以最后就要再把它对应的x,y换回来。

下边就是代码实现:

#include<iostream>
#include<cmath>
#include<cstdio>
#define INF 1e9+7
using namespace std;
int ABS(int a)
{
    return a<0?-a:a;
}
int exgcd(int a,int b,int &x,int &y)
{
    if(b==0){x=1;y=0;return a;}
    else
    {
        int d=exgcd(b,a%b,y,x);
        y-=a/b*x;
        return d;
    }
}
int gcd(int a,int b)
{
    int e;
    if(a<b)e=a,a=b,b=e;
    return gcd(b,a%b);
}
int main()
{
    int a,b,c,d;
    while(scanf("%d%d%d",&a,&b,&c),a|b|c)
    {
        int x0,y0,d,i,flag=0;
        if(a<b)
        {
            flag=1;
            swap(a,b);
        }
        d=exgcd(a,b,x0,y0);
        x0=x0*(c/d);
        y0=y0*(c/d);
        int t=y0/(a/d),ans=INF,u,v;
        for(i=t-1;i<=t+1;i++)
        {
            int x=x0+b/d*i;
            int y=y0-a/d*i;
            if(ABS(x)+ABS(y)<ans)
            {
                ans=ABS(x)+ABS(y);
                u=ABS(x);
                v=ABS(y);
            }
        }
        if(flag)
            printf("%d %d\n",v,u);
        else
            printf("%d %d\n",u,v);
    }
    return 0;
}


0 0
原创粉丝点击