概念
裴蜀定理(Bézout’s Identity)是数论中的一个重要定理,涉及整数的线性组合。定理陈述如下:
对于任何整数 a 和 b,如果 d 是 a 和 b 的最大公约数,那么存在整数 x 和 y 使得: ax+by=d
换句话说,最大公约数 d 可以表示为 a 和 bbb 的线性组合。
欧几里得算法证明
欧几里得算法是一种用于计算两个整数的最大公约数的算法。我们可以利用这个算法来证明裴蜀定理。
- 算法步骤:
- 如果 b=0 ,那么 a 就是 a 和 b 的最大公约数。此时 a=d ,且 a⋅1+b⋅0=a。
- 否则,令 r 是 a 除以 b 的余数,即 a=bq+r ,其中 q 是商。然后用欧几里得算法递归地计算 b 和 r 的最大公约数。
- 证明过程:
- 首先,我们知道 d=gcd(a,b) 也是 d=gcd(b,r) ,因为 r=a−bq 。根据递归过程,我们可以不断减小问题的规模,最终在某一步骤中,我们会得到 r=0 ,此时 b 是最大公约数。
- 在每一步,我们可以记录线性组合的形式。具体来说: r=a−bq 如果我们知道 b 和 r 的最大公约数可以写成: b⋅x1+r⋅y1=d 那么我们可以用 r=a−bq 替换 r: b⋅x1+(a−bq)⋅y1=d 展开并整理得到: a⋅y1+b⋅(x1−qy1)=d 因此,我们可以看到 d 依然是 a 和 b 的线性组合。
- 详细的证明递归部分:
- 初始情况:如果 b=0 ,则最大公约数 d=a ,且 a⋅1+b⋅0=a ,此时 x=1 和 y=0 。
- 递归情况:使用欧几里得算法得到 a=bq+r ,则 gcd(a,b)=gcd(b,r) ,我们可以继续应用算法到 b 和 r 。通过递归地应用线性组合,我们最终可以写出最大公约数的形式。
通过这个过程,我们证明了裴蜀定理,即对于任何两个整数 a 和 b,它们的最大公约数 d 总可以表示成它们的某个线性组合形式 ax+by=d 。
推广
对于任意整数 a1,a2,…,an ,如果 d 是这些整数的最大公约数,那么存在整数 x1,x2,…,xn 使得: a1x1+a2x2+⋯+anxn=d
换句话说,多个整数的最大公约数 d 可以表示为这些整数的线性组合。
模板
inline int gcd(int x, int y) { return y ? gcd(y, x % y) : !x; }
int n;
int main() {
scanf("%d", &n);
int ans = 0, tmp;
for (int i = 1; i <= n; i++) {
scanf("%d", &tmp);
if (tmp < 0) tmp = -tmp;
ans = gcd(ans, tmp);
}
printf("%d", ans);
}
模板题
P4549 【模板】裴蜀定理 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
给定一个包含 n 个元素的整数序列 A,记作 A1, A2, A3, …, An。
我们的目标是求另一个包含 n 个元素的待定整数序列 X,其中 S = ∑(Ai × Xi)(i 从 1 到 n)。要求 S > 0 且 S 尽可能的小。
#include <bits/stdc++.h>
using namespace std;
int main(){
int n;cin>>n;
vector<int> v(n);
for(int &i:v)cin>>i;
int g=v.front();
for(int i:v)g=gcd(g,i);
cout<<g<<endl;
return 0;
}
B-Crash Test_2024牛客暑期多校训练营3 (nowcoder.com)
我们考虑以下碰撞测试的简化版本。最初,汽车的前部朝向墙壁,距离墙壁 D 米。该碰撞测试提供了 n 种助推器,其中第 i 种助推器的推力性能为 h,并且每种类型的助推器都有充足的数量。假设汽车前部和墙壁之间的当前距离为 d,我们使用推力性能为 h 的助推器。当 d≥h 时,汽车将向前移动 h 米,然后停止。否则,汽车将向前移动 d 米,撞到墙上,然后反弹 h−d 米,然后停下来,仍然面向墙壁。
现在,您想知道,通过任意数量的操作(包括无操作),汽车前部和墙壁之间的最小距离是多少?
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main() {
int n,m;
cin>>n>>m;
vector<int> v(n);
for(int &i:v)cin>>i;
int g=v.front();
for(int i:v)g=gcd(g,i);
int x=m/g;
cout<<min(m-x*g,(x+1)*g-m);
return 0;
}