裴蜀定理&&扩展欧几里得定理

裴蜀定理(又称贝祖定理)

理论

一定存在整数 x,yx, yx,y,满足 ax+by=gcd(a,b)ax + by = gcd(a, b)ax+by=gcd(a,b)

4x+6y=24x + 6y = 24x+6y=2,有整数解 x=−1,y=1x = -1, y = 1x=1,y=1
4x+6y=34x + 6y = 34x+6y=3,即 x=3−6y4x = \frac{3 - 6y}{4}x=436y 无整数解。

证明:

设取整数 x0,y0x_0, y_0x0,y0 时,ax+byax + byax+by 的最小正整数为 sss

ax0+by0=sax_0 + by_0 = sax0+by0=s

gcd(a,b)∣ax0gcd(a, b) \mid ax_0gcd(a,b)ax0gcd(a,b)∣by0gcd(a, b) \mid by_0gcd(a,b)by0

gcd(a,b)∣s⋯⋯(1)gcd(a, b) \mid s \cdots\cdots (1)gcd(a,b)s⋯⋯(1)

a=qs+r(0≤r<s)a = qs + r (0 \leq r < s)a=qs+r(0r<s)

r=a−qsr = a - qsr=aqs

=a−q(ax0+by0)= a - q(ax_0 + by_0)=aq(ax0+by0)

=a(1−qx0)+b(−qy0)= a(1 - qx_0) + b(-qy_0)=a(1qx0)+b(qy0)

=ax+by= ax + by=ax+by

sss 是最小正整数,故 r=0r = 0r=0

所以 s∣as \mid asa,同理 s∣bs \mid bsb
s∣gcd(a,b)⋯⋯(2)s \mid gcd(a, b) \cdots\cdots (2)sgcd(a,b)⋯⋯(2)

(1)(2)(1)(2)(1)(2)s=gcd(a,b)s = gcd(a, b)s=gcd(a,b)。证毕。

裴蜀定理推广
一定存在整数 x,yx, yx,y,满足 ax+by=gcd(a,b)×nax + by = gcd(a, b) \times nax+by=gcd(a,b)×n

4x+6y=84x + 6y = 84x+6y=8,有整数解 x=−4,y=4x = -4, y = 4x=4,y=4

裴蜀定理再推广
一定存在整数 X1⋯XiX_1 \cdots X_iX1Xi,满足 ∑i=1nAiXi=gcd(A1,A2,⋯ ,An)\sum_{i = 1}^{n} A_iX_i = gcd(A_1, A_2, \cdots, A_n)i=1nAiXi=gcd(A1,A2,,An)

4x1+6x2+2x3=44x_1 + 6x_2 + 2x_3 = 44x1+6x2+2x3=4,有整数解 x1=1,x2=0,x3=0x_1 = 1, x_2 = 0, x_3 = 0x1=1,x2=0,x3=0

裴蜀定理扩展
ax+by=nax + by = nax+by=n

结论:

  • n>ab−a−bn > ab - a - bn>abab,有解
  • n=0n = 0n=0,有解
  • n<0n < 0n<0,无解
  • ax+by=nax + by = nax+by=n 有解,则 ax+by=ab−a−b−nax + by = ab - a - b - nax+by=ababn 无解

注意

欧几里得算法求 gcd(a,b)gcd(a, b)gcd(a,b)

如果代入负数,结果会返回负数

例:gcd(8,−4)=−4gcd(8, -4) = -4gcd(8,4)=4

如果系数 AiA_iAi 为负数,

gcdgcdgcd 时可代入其绝对值,

确保所求最大公约数为正数,

这样并不会影响解的存在。

例题

P4549 【模板】裴蜀定理

题目描述
给定一个包含 nnn 个元素的整数序列 AAA,记作 A1,A2,A3,...,AnA_1,A_2,A_3,...,A_nA1,A2,A3,...,An
求另一个包含 nnn 个元素的待定整数序列 XXX,记 S=∑i=1nAi×XiS=\sum\limits_{i=1}^nA_i\times X_iS=i=1nAi×Xi,使得 S>0S>0S>0SSS 尽可能的小。

输入格式
第一行一个整数 nnn,表示序列元素个数。
第二行 nnn 个整数,表示序列 AAA

输出格式
一行一个整数,表示 S>0S>0S>0 的前提下 SSS 的最小值。

输入输出样例 #1
输入 #1

2
4059 -1782

输出 #1

99

说明/提示
对于 100%100\%100% 的数据,1≤n≤201 \le n \le 201n20∣Ai∣≤105|A_i| \le 10^5Ai105,且 AAA 序列不全为 000

#include<bits/stdc++.h>
using namespace std;
int gcd(int a, int b)
{
	return b ? gcd(b, a % b) : a;
}
int main()
{
	int n, ans;
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		int x;
		cin >> x;
		if (i == 1)
		{
			ans = abs(x);
		}
		else
		{
			ans = gcd(ans, abs(x));
		}
	}
	cout << ans;
	return 0;
}

买不到的数目

题目描述
小明开了一家糖果店。他别出心裁:把水果糖包成 4 颗一包和 7 颗一包的两种。糖果不能拆包卖。
小朋友来买糖的时候,他就用这两种包装来组合。当然有些糖果数目是无法组合出来的,比如要买 10 颗糖。
你可以用计算机测试一下,在这种包装情况下,最大不能买到的数量是 17。大于 17 的任何数字都可以用 4 和 7 组合出来。
本题的要求就是在已知两个包装的数量时,求最大不能组合出的数字。
输入描述
输入两个正整数,表示每种包装中糖的颗数(都不多于 1000 )。
输出描述

输出一个正整数,表示最大不能买到的糖数。
不需要考虑无解的情况
输入输出样例
示例
输入

4 7

输出

17
#include <iostream>
using namespace std;
int x, y;
int main()
{
    cin >> x >> y;
    cout << x * y - x - y << endl;
    return 0;
}

扩展欧几里得算法

理论

问题1:

ax+by=gcd(a,b)ax + by = gcd(a, b)ax+by=gcd(a,b) 的一组整数解

b=0b = 0b=0ax+by=aax + by = aax+by=a 故而 x=1,y=0x = 1, y = 0x=1,y=0
b≠0b \neq 0b=0
由欧几里得算法,gcd(a,b)=gcd(b,a%b)gcd(a, b) = gcd(b, a\%b)gcd(a,b)=gcd(b,a%b)
由裴蜀定理,
gcd(a,b)=ax+bygcd(a, b) = ax + bygcd(a,b)=ax+by
gcd(b,a%b)=bx1+(a%b)y1gcd(b, a\%b) = bx_1 + (a\%b)y_1gcd(b,a%b)=bx1+(a%b)y1
=bx1+(a−⌊ab⌋×b)y1= bx_1 + (a - \lfloor\frac{a}{b}\rfloor\times b)y_1=bx1+(aba×b)y1
=ay1+b(x1−aby1)= ay_1 + b(x_1 - \frac{a}{b}y_1)=ay1+b(x1bay1)

所以 x=y1x = y_1x=y1y=x1−aby1y = x_1 - \frac{a}{b}y_1y=x1bay1
可以用递归算法,先求出下一层的 x1,y1x_1, y_1x1,y1,再回代到上一层,层层回代,可求特解(x0,y0)(x_0, y_0)(x0,y0)

构造通解
{x=x0+bgcd(a,b)∗ky=y0−agcd(a,b)∗k\begin{cases} x = x_0 + \frac{b}{gcd(a, b)}*k \\ y = y_0 - \frac{a}{gcd(a, b)}*k \end{cases}{x=x0+gcd(a,b)bky=y0gcd(a,b)ak (考虑 ax+by=0ax + by = 0ax+by=0 构造)

例:8x+6y=28x + 6y = 28x+6y=2,解: (1,−1),(4,−5),(7,−9)⋯(1, -1), (4, -5), (7, -9)\cdots(1,1),(4,5),(7,9)

//欧几里得算法
int gcd(int a, int b) {
	if (b == 0) {
		return 0;
	}
	return gcd(b, a % b);
}
int exgcd(int a, int b, int& x, int& y) {
	if (b == 0) {
		int x = 1, y = 0;
		return a;
	}
	int x1, y1, d;
	d = exgcd(b, a % b, x1, y1);
	x = y1, y = x1 - a / b * y1;
	return d;
}

问题2:

求不定方程 ax+by=cax + by = cax+by=c 的一组整数解

  1. gcd(a,b)∣cgcd(a, b) \mid cgcd(a,b)c,则有整数解
    • 先用扩欧算法求 ax+by=gcd(a,b)ax + by = gcd(a, b)ax+by=gcd(a,b) 的解
    • 再乘以 c/gcd(a,b)c / gcd(a, b)c/gcd(a,b),即得原方程的特解(x0,y0)(x_0, y_0)(x0,y0)
    • 例:8x+6y=68x + 6y = 68x+6y=6,解得 x=3,y=−3x = 3, y = -3x=3,y=3

构造通解
{x=x0+bgcd(a,b)∗ky=y0−agcd(a,b)∗k\begin{cases} x = x_0 + \frac{b}{gcd(a, b)}*k \\ y = y_0 - \frac{a}{gcd(a, b)}*k \end{cases}{x=x0+gcd(a,b)bky=y0gcd(a,b)ak (考虑 ax+by=0ax + by = 0ax+by=0 构造)

  1. gcd(a,b)∤cgcd(a, b) \nmid cgcd(a,b)c,则无整数解。
    • 例:8x+6y=38x + 6y = 38x+6y=3x=3−6y8x = \frac{3 - 6y}{8}x=836y
#include<bits/stdc++.h>
using namespace std;
int exgcd(int a, int b, int& x, int& y) {
	if (b == 0) {
		x = 1, y = 0;
		return a;
	}
	int x1, y1, d;
	d = exgcd(b, a % b, x1, y1);
	x = y1;
	y = x1 - a / b * y1;
	return d;
}
int main() {
	int a, b, c, x, y;
	cin >> a >> b >> c;
	int d = exgcd(a, b, x, y);
	if (c % d == 0) {
		printf("%d %d", c / d * x, c / d * y);
	}
	else {
		puts("none");
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值