数论——扩展欧几里得算法

扩展欧几里得算法

定义:

通常谈到最大公因子时, 我们都会提到一个非常基本的事实: 给予二整数 a 与 b, 必存在有整数 x 与 y 使得ax + by = gcd(a,b)。有两个数a,b,对它们进行辗转相除法,可得它们的最大公约数——这是众所周知的。然后,收集辗转相除法中产生的式子,倒回去,可以得到ax+by=gcd(a,b)的整数解。

应用:

求解线性同余方程,求逆元

算法原理描述

( 1 ) a x i   + b y i = g c d ( a , b ) (1)ax_i\ +by_i = gcd(a, b) (1)axi +byi=gcd(a,b)
( 2 ) b x i − 1 + ( a % b ) y i − 1 = g c d ( b , a % b ) (2)bx_{i - 1} + (a \% b) y_{i - 1} = gcd(b, a \% b) (2)bxi1+(a%b)yi1=gcd(b,a%b)
( 3 ) a % b ) x i − 2 + [ b % ( a % b ) ] y i − 2 = g c d ( b , a % b ) (3)a \% b)x_{i - 2} + [b \%(a \% b) ]y_{i - 2} = gcd(b, a \% b) (3)a%b)xi2+[b%(a%b)]yi2=gcd(b,a%b)
. . . . . . . . ........ ........
( n ) d ∗ 1 + 0 = g c d ( a , b ) (n)d* 1 + 0 = gcd(a, b) nd1+0=gcd(a,b)
(1)、(2)式,(2)式可以转换成 a y i − 1 + b ( x i − 1 − ( a / / b ) y i − 1 ) ay_{i - 1} + b(x_{i - 1} - (a // b)y_{i - 1}) ayi1+b(xi1(a//b)yi1),可以求得 x i = y i − 1 x_i = y_{i - 1} xi=yi1, y i = x i − 1 − ( a / / b ) y i − 1 y_{i} = x_{i - 1} - (a // b)y_{i - 1} yi=xi1(a//b)yi1
同理(2)式转换为(1)式形式,相对于(3)式的关系也是一样的,可以通过递归实现

例题

模板题

给定 n 对正整数 ai,bi,对于每对数,求出一组 xi,yi,使其满足 ai×xi+bi×yi=gcd(ai,bi)。

输入格式
第一行包含整数 n。

接下来 n 行,每行包含两个整数 ai,bi。

输出格式
输出共 n 行,对于每组 ai,bi,求出一组满足条件的 xi,yi,每组结果占一行。

本题答案不唯一,输出任意满足条件的 xi,yi 均可。

数据范围
1≤n≤10^5,
1≤ai,bi≤2×10^9
输入样例:
2
4 6
8 18
输出样例:
-1 1
-2 1

n = int(input())
def exgcd(a, b) :
	if b == 0 :
		return 1, 0
	x, y = exgcd(b, a % b)
	x, y = y, x - (a // b) * y
	return x, y, d
for i in range(n) :
	a, b = map(int, input().split())
	res = exgcd(a, b)
	print(res[0], res[1], end = " ")
	print()

求线性同余方程

给定 n 组数据 ai,bi,mi,对于每组数求出一个 xi,使其满足 a i × x i ≡ b i ( m o d   m i ) a_i×x_i≡b_i(mod \ m_i) ai×xibi(mod mi),如果无解则输出 impossible。

输入格式
第一行包含整数 n。

接下来 n 行,每行包含一组数据 ai,bi,mi。

输出格式
输出共 n 行,每组数据输出一个整数表示一个满足条件的 xi,如果无解则输出 impossible。

每组数据结果占一行,结果可能不唯一,输出任意一个满足条件的结果均可。

输出答案必须在 int 范围之内。

数据范围
1≤n≤10^5,
1≤ai,bi,mi≤2×10^9
输入样例:
2
2 3 6
4 3 5
输出样例:
impossible
-3

思路讲解

a × x ≡ b ( m o d   m ) a×x≡b(mod \ m) a×xb(mod m)=> a x + m y = b ax + my = b ax+my=b,则 g c d ( a , m ) ∣ b gcd(a,m) | b gcd(a,m)b,通过扩展欧几里得算法 a x ′ + m y ′ = g c d ( a , m ) ax^{'} + my^{'} = gcd(a, m) ax+my=gcd(a,m)可以求得 a ∗ x ′ ≡ g c d ( a , m ) ( m o d   m ) a * x^{'}≡gcd(a, m) (mod \ m) axgcd(a,m)(mod m),中的x’由模的乘法运算知, a ∗ x ′ ∗ ( b / / g c d ( a , m ) ) m o d   m ≡ b ( m o d   m ) a * x^{'} * (b // gcd(a, m)) mod \ m≡b (mod \ m) ax(b//gcd(a,m))mod mb(mod m)

n = int(input())

def exgcd(a, b) :
	if b == 0 :
		return 1, 0, a
	x, y, d = exgcd(b, a % b)
	return y, x - (a // b) * y, d

for i in range(n) :
	a, b, m = map(int, input().split())
	res = exgcd(a, m)
	if b % res[2] != 0 :
		print("impossible")
	else :
		print(res[0] * (b // res[2]) % m)
总结

这篇关于欧几里得算法的讲解算是非常详细了,此外欧几里得算法对于求解逆元是非常有帮助的,相当于线性同余方程 a × x ≡ b ( m o d   m ) a×x≡b(mod \ m) a×xb(mod m),中b = 1的情况

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值