裴蜀定理
a , b a,b a,b 是整数,且 gcd ( a , b ) = d \gcd(a,b)=d gcd(a,b)=d,那么对于任意的整数 x , y x,y x,y, a x + b y ax+by ax+by 都一定是 d d d 的倍数。特别地,一定存在整数 x , y x,y x,y,使 a x + b y = d ax+by=d ax+by=d 成立。
换种说法,若 a x + b y = c ax+by=c ax+by=c 有解,当且仅当 c c c 是 gcd ( a , b ) \gcd(a,b) gcd(a,b) 的倍数。
证明:
令 gcd ( a , b ) = p \gcd(a,b)=p gcd(a,b)=p。
一、必要性:如果有整数解,那么 c c c 是 p p p 的倍数。
a = a ′ ∗ p , b = b ′ ∗ p a=a'*p,b=b'*p a=a′∗p,b=b′∗p
a x + b y = a ′ ∗ p ∗ x + b ′ ∗ p ∗ y = p ∗ ( a ′ x + b ′ y ) = c ax+by=a'*p*x+b'*p*y=p*(a'x+b'y)=c ax+by=a′∗p∗x+b′∗p∗y=p∗(a′x+b′y)=c。
因此 c c c 是 p p p 的倍数。必要性得证。
二、充分性:如果 c c c 是 p p p 的倍数,那么就有整数解。
根据欧几里得算法,求 gcd \gcd gcd 的时候,最后一定是 a = p , b = 0 a=p,b=0 a=p,b=0。
此时满足 a x + b y = c ax+by=c ax+by=c 的解很容易找,例如 x = c p , y = 0 x=\frac{c}{p},y=0 x=pc,y=0。
然后考虑从 ( b , a % b ) (b,a\%b) (b,a%b) 的整数解推到 ( a , b ) (a,b) (a,b) 的整数解。(有点像归纳)
设 b ∗ x 1 + a % b ∗ y 1 = c b*x1+a\%b*y1=c b∗x1+a%b∗y1=c
a x + b y = b ∗ x 1 + a % b ∗ y 1 = b ∗ x 1 + ( a − ⌊ a b ⌋ ∗ b ) ∗ y 1 = a ∗ y 1 + b ∗ ( x 1 − ⌊ a b ⌋ ∗ y 1 ) ax+by=b*x1+a\%b*y1=b*x1+(a-\lfloor\frac{a}{b}\rfloor*b)*y1=a*y1+b*(x1-\lfloor\frac{a}{b}\rfloor*y1) ax+by=b∗x1+a%b∗y1=b∗x1+(a−⌊ba⌋∗b)∗y1=a∗y1+b∗(x1−⌊ba⌋∗y1)
显然当 x = y 1 , y = x 1 − ⌊ a b ⌋ ∗ b x=y1,y=x1-\lfloor\frac{a}{b}\rfloor*b x=y1,y=x1−⌊ba⌋∗b 时等式成立,则必然有整数解。充分性得证。
扩展欧几里得
其实扩展欧几里得就是要求类似 a x + b y = c ax+by=c ax+by=c 这样式子的解。而在刚刚裴蜀定理充分性的证明中,已经将如果求一组特殊解的过程说了。
即:先求出 gcd \gcd gcd,并令此时 x = p gcd , y = 0 x=\frac{p}{\gcd},y=0 x=gcdp,y=0,然后一步一步向上推导回去。
如方程 99 x + 78 y = 6 99x+78y=6 99x+78y=6,求解过程如下表所示:( x = y 1 , y = x 1 − ⌊ a b ⌋ ∗ b x=y1,y=x1-\lfloor\frac{a}{b}\rfloor*b x=y1,y=x1−⌊ba⌋∗b)
a | b | ⌊ a b ⌋ \lfloor\frac{a}{b}\rfloor ⌊ba⌋ | x | y |
---|---|---|---|---|
99 | 78 | 1 | -22 | 28 |
78 | 21 | 3 | 6 | -22 |
21 | 15 | 1 | -4 | 6 |
15 | 6 | 2 | 2 | -4 |
6 | 3 | 2 | 0 | 2 |
3 | 0 | - | x=gcd(99,78)=2 | 0 |
验证一下: 99 ∗ ( − 22 ) + 78 ∗ 28 = − 2178 + 2184 = 6 99*(-22)+78*28=-2178+2184=6 99∗(−22)+78∗28=−2178+2184=6。
void exgcd(int a,int b,int &d,int &x,int &y)
{
if (b==0){ d=a;x=c/a;y=0;}
else
{
int x1,y1;
exgcd(b,a % b,d,x1,y1);
x=y1;
y=x1-a/b*y1;
}
}
做到这里,我们已经求出来了一组特解,那么如何求出一般解呢?
我们设特解 ( x 0 , y 0 ) (x0,y0) (x0,y0) 的下一组解是 ( x 0 + d 1 , y 0 + d 2 ) (x0+d1,y0+d2) (x0+d1,y0+d2),有
a ∗ x 0 + b ∗ y 0 = a ∗ ( x 0 + d 1 ) + b ∗ ( y 0 + d 2 ) = c a*x0+b*y0=a*(x0+d1)+b*(y0+d2)=c a∗x0+b∗y0=a∗(x0+d1)+b∗(y0+d2)=c
a ∗ d 1 + b ∗ d 2 = 0 a*d1+b*d2=0 a∗d1+b∗d2=0
d 1 d 2 = − b a \dfrac{d1}{d2}=-\dfrac{b}{a} d2d1=−ab
约分得 d 1 d 2 = − b gcd ( a , b ) a gcd ( a , b ) \dfrac{d1}{d2}=-\dfrac{\frac{b}{\gcd(a,b)}}{\frac{a}{\gcd(a,b)}} d2d1=−gcd(a,b)agcd(a,b)b。
而根据定义, d 1 d1 d1 应该尽可能小,所以 d 1 = b gcd ( a , b ) , d 2 = − a gcd ( a , b ) d1=\dfrac{b}{\gcd(a,b)},d2=-\dfrac{a}{\gcd(a,b)} d1=gcd(a,b)b,d2=−gcd(a,b)a。
因此 a x + b y = c ax+by=c ax+by=c 的一般解形式就可以表示成 x = x 0 + k ∗ ( b gcd ( a , b ) ) , y = y 0 − k ∗ ( a gcd ( a , b ) ) x=x0+k*(\frac{b}{\gcd(a,b)}),y=y0-k*(\frac{a}{\gcd(a,b)}) x=x0+k∗(gcd(a,b)b),y=y0−k∗(gcd(a,b)a),其中 k ∈ Z k\in \mathbb{Z} k∈Z。
拓展:
对于整数序列 A 1 , A 2 , A 3 , … , A n A_1,A_2,A_3,\dots,A_n A1,A2,A3,…,An 是否存在 X 1 , X 2 , X 3 , … , X n X_1,X_2,X_3,\dots,X_n X1,X2,X3,…,Xn 使得 A 1 ∗ X 1 + A 2 ∗ X 2 + A 3 ∗ X 3 + ⋯ + A n ∗ X n = C A_1*X_1+A_2*X_2+A_3*X_3+\dots+A_n*X_n=C A1∗X1+A2∗X2+A3∗X3+⋯+An∗Xn=C 其中满足 gcd ( A 1 , A 2 , A 3 , … , A n ) ∣ C , n ≥ 2 \gcd(A_1,A_2,A_3,\dots,A_n)|C,n\ge 2 gcd(A1,A2,A3,…,An)∣C,n≥2.
结论:存在。
证明:使用数学归纳。
当 n = 2 n=2 n=2 时成立(根据裴蜀定理)。
设当 n = k n=k n=k 时成立,考虑 n = k + 1 n=k+1 n=k+1 时是否成立。
gcd ( A 1 , A 2 , A 3 , … , A k ) ∗ x + A k + 1 ∗ X k + 1 = C \gcd(A_1,A_2,A_3,\dots,A_k)*x+A_{k+1}*X_{k+1}=C gcd(A1,A2,A3,…,Ak)∗x+Ak+1∗Xk+1=C 有解,因为 gcd ( gcd ( A 1 , A 2 , A 3 , … , A k ) , A k + 1 ) = gcd ( A 1 , A 2 , A 3 , … , A k + 1 ) \gcd(\gcd(A_1,A_2,A_3,\dots,A_k),A_{k+1})=\gcd(A_1,A_2,A_3,\dots,A_{k+1}) gcd(gcd(A1,A2,A3,…,Ak),Ak+1)=gcd(A1,A2,A3,…,Ak+1),而 gcd ( A 1 , A 2 , A 3 , … , A k + 1 ) ∣ C \gcd(A_1,A_2,A_3,\dots,A_{k+1})|C gcd(A1,A2,A3,…,Ak+1)∣C。
同时 A 1 ∗ X 1 + A 2 ∗ X 2 + A 3 ∗ X 3 + ⋯ + A k ∗ X k = gcd ( A 1 , A 2 , A 3 , … , A k ) ∗ x A_1*X_1+A_2*X_2+A_3*X_3+\dots+A_k*X_k=\gcd(A_1,A_2,A_3,\dots,A_k)*x A1∗X1+A2∗X2+A3∗X3+⋯+Ak∗Xk=gcd(A1,A2,A3,…,Ak)∗x 也有解。
得证。并且上述证明过程也可以用于求解过程。
int main()
{
scanf("%d",&n);
gcd[0]=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
gcd[i]=Gcd(gcd[i-1],a[i]);
}
scanf("%d",&c);
if (c % gcd[n]==0)
{
y[n]=c/gcd[n];
for (int i=n;i>1;i--)
exgcd(gcd[i-1],a[i],gcd[i]*y[i],y[i-1],x[i]);
x[1]=y[1];
for(int i=1;i<=n;i++)
printf("%d ",x[i]);
}
return 0;
}