扩展欧几里得算法求的是方程

扩展欧几里得算法_欧几里得算法

的解。原理如下

 


扩展欧几里得算法_ios_02

,当

扩展欧几里得算法_ios_03

时,

扩展欧几里得算法_ios_04

,此时

扩展欧几里得算法_#include_05

,否则设

 

     

扩展欧几里得算法_#include_06

 

由于

扩展欧几里得算法_#include_07

,所以进一步得到

 

     

扩展欧几里得算法_欧几里得算法_08

 

所以得到


                   

扩展欧几里得算法_欧几里得算法_09

 

代码:


void extend_Euclid(LL a, LL b, LL &x, LL &y)
{
    if(b == 0)
    {
        x = 1;
        y = 0;
        return;
    }
    extend_Euclid(b, a % b, x, y);
    LL tmp = x;
    x = y;
    y = tmp - (a / b) * y;
}



题目: http://poj.org/problem?id=2142

 

题意:有两种类型的砝码质量分别为

扩展欧几里得算法_ios_10


扩展欧几里得算法_ios_11

,要求称出质量为

扩展欧几里得算法_ios_12

的物品,要求

扩展欧几里得算法_ios_10

的数量

扩展欧几里得算法_欧几里得算法_14


扩展欧几里得算法_ios_11

的数量

扩展欧几里得算法_ios_16

的和

扩展欧几里得算法_欧几里得算法_17

     最小,如果有多个

扩展欧几里得算法_欧几里得算法_17

最小值,取

扩展欧几里得算法_ios_19

最小的。


分析:扩展欧几里得求出特解后,把

扩展欧几里得算法_欧几里得算法_14

转化为最小正值,即

扩展欧几里得算法_ios_21


扩展欧几里得算法_#include_22

,若     求出的

扩展欧几里得算法_ios_16

为负值,则把

扩展欧几里得算法_ios_16

变正,意思就是砝码放置的位置有左右之分,可以左面的减去右面的,也可以右面     的减去左面的。同理,再求出

扩展欧几里得算法_ios_16

为最小合法正值时

扩展欧几里得算法_欧几里得算法_14

的解,将这两种情况比较取小的即可。


代码:

#include <iostream>
#include <string.h>
#include <stdio.h>

using namespace std;

int gcd(int a, int b)
{
    return b ? gcd(b, a % b) : a;
}

void extend_Euclid(int a, int b, int &x, int &y)
{
    if(b == 0)
    {
        x = 1;
        y = 0;
        return;
    }
    extend_Euclid(b, a % b, x, y);
    int tmp = x;
    x = y;
    y = tmp - (a / b) * y;
}

int main()
{
    int a, b, n;
    while(scanf("%d%d%d",&a,&b,&n)!=EOF)
    {
        if(a + b + n == 0) break;
        int d = gcd(a, b);
        a /= d;
        b /= d;
        n /= d;
        int x, y;
        extend_Euclid(a, b, x, y);
        int tx = x * n;
        tx = (tx % b + b) % b;
        int ty = (n - a * tx) / b;
        if(ty < 0) ty = -ty;
        y *= n;
        y = (y % a + a) % a;
        x = (n - b * y) / a;
        if(x < 0) x = -x;
        if(x + y > tx + ty)
        {
            x = tx;
            y = ty;
        }
        printf("%d %d\n",x,y);
    }
    return 0;
}

 

题目:http://acm.hit.edu.cn/hoj/problem/view?id=2815

 

题意:给定两个数

扩展欧几里得算法_ios_27


扩展欧几里得算法_ios_28

,其中

扩展欧几里得算法_ios_29

,只对

扩展欧几里得算法_ios_27


扩展欧几里得算法_ios_28

进行加减操作,求最少需要多少步能得到1


分析:典型的扩展欧几里得算法,注意有些需要特判。


代码:

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>

using namespace std;
typedef long long LL;

LL gcd(LL a,LL b)
{
    return b ? gcd(b,a%b):a;
}

void extend_Euclid(LL a,LL b,LL &x,LL &y)
{
    if(b == 0)
    {
        x = 1;
        y = 0;
        return;
    }
    extend_Euclid(b,a%b,x,y);
    LL tmp = x;
    x = y;
    y = tmp - (a / b) * y;
}

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        LL a,b;
        cin>>a>>b;
        if(a < b) swap(a,b);
        LL g = gcd(a,b);
        if(g != 1)
        {
            puts("-1");
            continue;
        }
        if(b == 1 && a == 2)
        {
            puts("1");
            continue;
        }
        if(b == 1)
        {
            puts("2");
            continue;
        }
        if(b == 0 && a == 1)
        {
            puts("1");
            continue;
        }
        LL x,y;
        extend_Euclid(a,b,x,y);
        LL ans = abs(x) + abs(y);
        if(x < 0)
        {
            LL tmp = abs(x + b) + abs(y-a);
            if(tmp < ans) ans = tmp;
        }
        else
        {
            LL tmp = abs(x - b) + abs(y + a);
            if(tmp < ans) ans = tmp;
        }
        cout<<ans - 1<<endl;
    }
    return 0;
}