Files
python/TangDou/AcWing/Math/P4549.md
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

120 lines
3.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

### 裴蜀定理(贝祖定理)
#### 定理
对任何整数 $a、b$ 和 $m$,关于未知数 $x$和 $y$ 的线性丢番图方程(称为裴蜀等式):
$$\LARGE ax+by=m$$
* 有整数解时当且仅当 $m$是$a$及$b$的最大公约数$d=gcd(a,b)$的倍数。
* 裴蜀等式有解时必然有无穷多个整数解,每组解$x,y$都称为**裴蜀数**
* 可用扩展欧几里得算法求解**裴蜀数**
#### 例子
例如,$12$和$42$的最大公约数是$6$,则方程$12x + 42y = 6$有解。
事实上有:
* $(−3)×12+1×42=6$
* $4×12+(−1)×42=6$
* $11×12+(-3)*42=6$
* ...
用计算机帮着算一下:
```c++
#include <bits/stdc++.h>
using namespace std;
int main() {
for (int x = -100; x <= 100; x++)
for (int y = -100; y <= 100; y++)
if (2 * x + y * 7 == 1) cout << x << " " << y << endl;
return 0;
}
```
#### 证明
看这个证明可能要好懂点
例:
$$\LARGE 2 * x + 4 * y = c$$
那么$c$无论如何都是偶数,换句话来说,$c$一定是$2$的倍数$2 = gcd(2,4)$
$$\LARGE 3 * x + 9 * y = c$$
那么同理$c$一定是$3$的倍数,因为上述等于 : $3 * x + 3 * 3 * y = c$
$3 * (x + 3 * y) = c$,外面乘了个$3$,那么$c$再怎么都是$3$的倍数,$3 = gcd(3,9)$
那么这个定理有什么用呢。当$x,y$为整数解的时候,$c$一定是$gcd(a,b)$的倍数,那么我们就可以求得当为整数解的时候,$c$的最小值肯定就是$gcd(a,b)$ //最大公约数的$1$倍。
[用几何方式证明裴蜀定理](https://www.bilibili.com/video/av200767266/)
[点到直线距离的公式证明](https://www.toutiao.com/video/6815606337615954439/)
[练习题 P4549 【模板】裴蜀定理](https://www.luogu.com.cn/problem/P4549)
#### 实现代码
```c++
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
scanf("%d", &n);
int d = 0, a;
for (int i = 1; i <= n; i++) {
scanf("%d", &a);
d = __gcd(d, abs(a));
}
printf("%d", d);
return 0;
}
```
---
#### 引理
<font color='blue' size=4><b>给定$a,b$,均是正整数且互质,那么由$ax+by,x>=0,y>=0$不能凑出的最大数是$ab-a-b$;</b></font>
[证明](https://blog.csdn.net/qq_38973721/article/details/79752734)
[练习题 蓝桥杯.买不到的数目](http://t.zoukankan.com/qwertiLH-p-9674097.html)
**解法I:采用引理解题**
```c++
#include<bits/stdc++.h>
using namespace std;
int main(){
int a, b;
scanf("%d %d",&a,&b);
printf("%d\n",a*b-a-b);
return 0;
}
```
**解法II:采用爆搜解题**
```c++
#include <bits/stdc++.h>
using namespace std;
int p, q, res;
/*
测试数据:
4 7
根据公式,最大无法凑出的是:4*7-4-7=17
*/
bool dfs(int x) {
if (x == 0) return true;
if (x >= p && dfs(x - p)) return true;
if (x >= q && dfs(x - q)) return true;
return false;
}
int main() {
scanf("%d %d", &p, &q);
for (int i = 1; i <= 1000; i++)
if (!dfs(i)) res = i;
printf("%d\n", res);
return 0;
}
```
---