You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
3.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

### 裴蜀定理(贝祖定理)
#### 定理
对任何整数 $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)$
那么这个定理有什么用呢。当$xy$为整数解的时候,$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+byx>=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;
}
```
---