数论——扩展欧几里得算法(exgcd)

 

求不定方程 a∗x+b∗y=1 的一组解的方法
由 a∗x1+b∗y1=gcd(a,b)=gcd(b,amod b)=b∗x2+[a−⌊a/b⌋∗b]∗y2=a∗y2+b∗(x2−y2∗⌊a/b⌋)

=>x1=y2
=>y1=x2−y2∗(a / b)

 

 

 

用途:
1)求解不定方程;
2)求解模线性方程(线性同余方程);
3)求解模的逆元;

1)求解不定方程

利用扩展欧几里得算法求解不定方程a∗x+b∗y=n的整数解的求解全过程,步骤如下:

(1)先计算Gcd(a,b),若n不能被Gcd(a,b)整除,则方程无整数解;否则,在方程两边同时除以Gcd(a,b),得到新的不定方程a2∗x+b2∗y=n2此时Gcd(a2,b2)=1;

(2)利用扩展欧几里德算法求出方程a2∗x+b2∗y=1的一组整数解x0,y0,则n2∗x0,n2∗y0是方程a2∗x+b2∗y=n2的一组整数解;

(3)根据数论中的相关定理,可得方程a2∗x+b2∗y=n2的所有整数解为:
x=n2∗x0+b2∗t
y=n2∗y0−a2∗t (t=0,1,2,……)
调整得到正整数解

 

 

LL exgcd(LL a, LL b, LL &x, LL &y) {  
    if(!b) {  
        x = 1;  
        y = 0;  
        return a;  
    }  
    LL ans = exgcd(b, a%b, x, y);  
    LL temp = x;  
    x = y;  
    y = temp - a / b * y;  
    return ans;  
}  
LL cal(LL a, LL b, LL c) {  
    LL x, y;  
    LL gcd = exgcd(a, b, x, y);  
    if(c % gcd != 0) return -1;  
    x *= c / gcd;  
    b /= gcd;  
    if(b < 0) b =- b;  
    LL ans = x % b;  
    if(ans <= 0) ans += b;  
    return ans;  
} 

数学一本通:注释此代码来自课本,未经测试,编译没问题

 

/*ax+by=GCD(x,y)->ax+(x-a/b*q)*b正向递归,返回时相应元素一一对应   */

#include<cstdio>//ax+by=GCD(a,b)
using namespace  std;
int extended_gcd(int a, int  b, int &x, int &y)
{
	int ret,temp;
	if (!b)
	{
		x = 1;
		y = 0;
		return a;//整个的最终函数返回的的值,最大公约数
	}
	extended_gcd(b, a%b, x, y);
	temp = x;
	x = y;
	y = temp - a / b * y;
	return ret;//递归逐步返回的公约数
}
int main()
{
	int a, b, x, y, z;
	scanf("%d%d", &a, &b);
	z = extended_gcd(a, b, x, y);
	printf("%d%d%d", z, x, y);//输出最大公约数和一组解
	return 0;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会敲代码的小帅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值