扩展欧几里德

先说欧几里德算法

int gcd(int a,int b)
{
    return b==0?a:gcd(b,a%b);
    //辗转相除,如果b为0,返回a;
}

扩展欧几里德
先贴代码

int exgcd(int a,int b,int &x,int &y)
{
    int d=a;
    if(b==0)
    {
        x=1,y=0;
    }
    else
    {
        d=exgcd(b, a%b, y, x);
        y-=(a/b)*x;
    }
    return d;
}

欧几里德算法递归最终的状态是: a= gcd , b = 0,这时,我们就会有: a*1 + b*0 = gcd
假设当前我们要处理的是求出 a 和 b的最大公约数,并求出 x 和 y 使得 a*x + b*y= gcd ,而我们已经求出了下一个状态:b 和 a%b 的最大公约数,并且求出了一组x1 和y1 使得: b*x1 + (a%b)*y1 = gcd , 那么这两个相邻的状态之间是否存在一种关系呢?
我们知道: a%b = a - (a/b)*b(这里的 “/” 指的是整除,例如 5/2=2 , 1/3=0),那么,我们可以进一步得到:

    gcd = b*x1 + (a-(a/b)*b)*y1

        = b*x1 + a*y1 – (a/b)*b*y1

        = a*y1 + b*(x1 – a/b*y1)

对比之前我们的状态:求一组 x 和 y 使得:a*x + b*y = gcd

就有:

    x = y1

    y = x1 – a/b*y1

于是你就很“容易“写出扩展欧几里德的递归算法,如上;


很多题目不是直接让你求ax+by=gcd,而是变相的问你是否存在一组解,使得ax+by=n

这里的n如果n%gcd(a,b)==0,就有解,否则一定无解。
但是有时候题目会包含隐含条件,要求x和y都要大于等于0,这个时候就不能直接判断了
我们知道,得到的x和y其实只是gcd的一组解,可以通过这组通解得到通解,假设得到特解x0,y0,则通解可表示为:

    x = x0 + (b/gcd)*t

    y = y0 – (a/gcd)*t

如果不清楚为什么来的,可以带入原方程,你会发现gcd并没有改变
得到通解后,通过

    x*=n/gcd(a,b);
    x=(x%(b/gcd)+b/gcd)%(b/gcd);

把x变成符合题意的正整数,再算出y,判断x和y是否都不为负数即可
贴一个代码:

#include<stdio.h>
#include<algorithm>
#include<iostream>
#define ll long long
using namespace std;
int exgcd(int a,int b,int &x,int &y)
{
    int d=a;
    if(b==0)
    {
        x=1,y=0;
    }
    else
    {
        d=exgcd(b, a%b, y, x);
        y-=(a/b)*x;
    }
    return d;
}
int gcd(int a,int b)
{
    return b==0?a:gcd(b,a%b);
}
int  main()
{
    int a,b,n;
    while(cin>>a>>b>>n)
    {
        int x,y;
        int gc=exgcd(a, b, x,y);
        if(n%gc!=0){printf("NO\n");continue;}
        x=x*n/gc;
        x=(x%(b/gc)+b/gc)%(b/gc);//把x变成正数(因为用exgcd可能求出负值)

        y=(n-x*a)/b;
        if(x>=0&&y>=0)
            printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值