一定存在整数 x , y x, y x,y,满足 a x + b y = g c d ( a , b ) ax + by = gcd(a, b) ax+by=gcd(a,b)
例 4 x + 6 y = 2 4x + 6y = 2 4x+6y=2,有整数解 x = − 1 , y = 1 x = -1, y = 1 x=−1,y=1。
而 4 x + 6 y = 3 4x + 6y = 3 4x+6y=3,即 x = 3 − 6 y 4 x = \frac{3 - 6y}{4} x=43−6y 无整数解。
证明:
设取整数 x 0 , y 0 x_0, y_0 x0,y0 时, a x + b y ax + by ax+by 的最小正整数为 s s s
即 a x 0 + b y 0 = s ax_0 + by_0 = s ax0+by0=s
因 g c d ( a , b ) ∣ a x 0 gcd(a, b) \mid ax_0 gcd(a,b)∣ax0, g c d ( a , b ) ∣ b y 0 gcd(a, b) \mid by_0 gcd(a,b)∣by0,
故 g c d ( a , b ) ∣ s ⋯ ⋯ ( 1 ) gcd(a, b) \mid s \cdots\cdots (1) gcd(a,b)∣s⋯⋯(1)
设 a = q s + r ( 0 ≤ r < s ) a = qs + r (0 \leq r < s) a=qs+r(0≤r<s)
r = a − q s r = a - qs r=a−qs
= a − q ( a x 0 + b y 0 ) = a - q(ax_0 + by_0) =a−q(ax0+by0)
= a ( 1 − q x 0 ) + b ( − q y 0 ) = a(1 - qx_0) + b(-qy_0) =a(1−qx0)+b(−qy0)
= a x + b y = ax + by =ax+by
因 s s s 是最小正整数,故 r = 0 r = 0 r=0
所以 s ∣ a s \mid a s∣a,同理 s ∣ b s \mid b s∣b,
故 s ∣ g c d ( a , b ) ⋯ ⋯ ( 2 ) s \mid gcd(a, b) \cdots\cdots (2) s∣gcd(a,b)⋯⋯(2)由 ( 1 ) ( 2 ) (1)(2) (1)(2) 得 s = g c d ( a , b ) s = gcd(a, b) s=gcd(a,b)。证毕。
裴蜀定理推广
一定存在整数 x , y x, y x,y,满足 a x + b y = g c d ( a , b ) × n ax + by = gcd(a, b) \times n ax+by=gcd(a,b)×n
例 4 x + 6 y = 8 4x + 6y = 8 4x+6y=8,有整数解 x = − 4 , y = 4 x = -4, y = 4 x=−4,y=4。
裴蜀定理再推广
一定存在整数 X 1 ⋯ X i X_1 \cdots X_i X1⋯Xi,满足 ∑ i = 1 n A i X i = g c d ( A 1 , A 2 , ⋯ , A n ) \sum_{i = 1}^{n} A_iX_i = gcd(A_1, A_2, \cdots, A_n) ∑i=1nAiXi=gcd(A1,A2,⋯,An)
例 4 x 1 + 6 x 2 + 2 x 3 = 4 4x_1 + 6x_2 + 2x_3 = 4 4x1+6x2+2x3=4,有整数解 x 1 = 1 , x 2 = 0 , x 3 = 0 x_1 = 1, x_2 = 0, x_3 = 0 x1=1,x2=0,x3=0。
裴蜀定理扩展
a x + b y = n ax + by = n ax+by=n
结论:
注意
欧几里得算法求 g c d ( a , b ) gcd(a, b) gcd(a,b)
如果代入负数,结果会返回负数
例: g c d ( 8 , − 4 ) = − 4 gcd(8, -4) = -4 gcd(8,−4)=−4
如果系数 A i A_i Ai 为负数,
求 g c d gcd gcd 时可代入其绝对值,
确保所求最大公约数为正数,
这样并不会影响解的存在。
题目描述
给定一个包含 n n n 个元素的整数序列 A A A,记作 A 1 , A 2 , A 3 , . . . , A n A_1,A_2,A_3,...,A_n A1,A2,A3,...,An。
求另一个包含 n n n 个元素的待定整数序列 X X X,记 S = ∑ i = 1 n A i × X i S=\sum\limits_{i=1}^nA_i\times X_i S=i=1∑nAi×Xi,使得 S > 0 S>0 S>0 且 S S S 尽可能的小。
输入格式
第一行一个整数 n n n,表示序列元素个数。
第二行 n n n 个整数,表示序列 A A A。
输出格式
一行一个整数,表示 S > 0 S>0 S>0 的前提下 S S S 的最小值。
输入输出样例 #1
输入 #1
2
4059 -1782
输出 #1
99
说明/提示
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 20 1 \le n \le 20 1≤n≤20, ∣ A i ∣ ≤ 1 0 5 |A_i| \le 10^5 ∣Ai∣≤105,且 A A A 序列不全为 0 0 0。
#include
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
using namespace std;
int x, y;
int main()
{
cin >> x >> y;
cout << x * y - x - y << endl;
return 0;
}
求 a x + b y = g c d ( a , b ) ax + by = gcd(a, b) ax+by=gcd(a,b) 的一组整数解
当 b = 0 b = 0 b=0 时 a x + b y = a ax + by = a ax+by=a 故而 x = 1 , y = 0 x = 1, y = 0 x=1,y=0
当 b ≠ 0 b \neq 0 b=0 时
由欧几里得算法, g c d ( a , b ) = g c d ( b , a % b ) gcd(a, b) = gcd(b, a\%b) gcd(a,b)=gcd(b,a%b)
由裴蜀定理,
g c d ( a , b ) = a x + b y gcd(a, b) = ax + by gcd(a,b)=ax+by
g c d ( b , a % b ) = b x 1 + ( a % b ) y 1 gcd(b, a\%b) = bx_1 + (a\%b)y_1 gcd(b,a%b)=bx1+(a%b)y1
= b x 1 + ( a − ⌊ a b ⌋ × b ) y 1 = bx_1 + (a - \lfloor\frac{a}{b}\rfloor\times b)y_1 =bx1+(a−⌊ba⌋×b)y1
= a y 1 + b ( x 1 − a b y 1 ) = ay_1 + b(x_1 - \frac{a}{b}y_1) =ay1+b(x1−bay1)
所以 x = y 1 x = y_1 x=y1, y = x 1 − a b y 1 y = x_1 - \frac{a}{b}y_1 y=x1−bay1
可以用递归算法,先求出下一层的 x 1 , y 1 x_1, y_1 x1,y1,再回代到上一层,层层回代,可求特解 ( x 0 , y 0 ) (x_0, y_0) (x0,y0)
构造通解
{ x = x 0 + b g c d ( a , b ) ∗ k y = y 0 − a g c d ( 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)b∗ky=y0−gcd(a,b)a∗k (考虑 a x + b y = 0 ax + by = 0 ax+by=0 构造)
例: 8 x + 6 y = 2 8x + 6y = 2 8x+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;
}
求不定方程 a x + b y = c ax + by = c ax+by=c 的一组整数解
构造通解
{ x = x 0 + b g c d ( a , b ) ∗ k y = y 0 − a g c d ( 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)b∗ky=y0−gcd(a,b)a∗k (考虑 a x + b y = 0 ax + by = 0 ax+by=0 构造)
#include
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;
}