证明裴蜀定理(一位刚学数论两天的初三生发明的证法)

裴蜀定理:对于整数 a , b a,b a,b,若 a , b a,b a,b 不全为0,则存在 x , y x,y x,y 使得 a × x + b × y = gcd(a,b) a \times x + b \times y = \text{gcd(a,b)} a×x+b×y=gcd(a,b)

不失一般性,设 0 ≤ a ≤ b 0 \le a \le b 0ab,对于 a < 0 a<0 a<0 则将 − a , b {-a,b} a,b 的解的 x x x 取反, b < 0 b<0 b<0 同理。

如: a = 3 , b = 2 {a=3,b=2} a=3,b=2 的一种解为 x = 3 , y = − 4 {x=3,y=-4} x=3,y=4,那么 a = − 3 , b = 2 {a=-3,b=2} a=3,b=2 的一组解就是 − 3 , − 4 {-3,-4} 3,4

s t 1 : a = 0 , gcd ( a , b ) = b st_1:a=0,\text{gcd}(a,b)=b st1a=0,gcd(a,b)=b

此时取 x = 0 , y = 1 x=0,y=1 x=0,y=1 a × x + b × y = b = gcd ( a , b ) a \times x+b \times y=b=\text{gcd}(a,b) a×x+b×y=b=gcd(a,b),条件成立。

s t 2 : a ≠ 0 , gcd ( a , b ) = 0 st_2:a \neq 0,\text{gcd}(a,b)=0 st2a=0,gcd(a,b)=0

v = b % a v=b\%a v=b%a v = b − t × v v=b-t \times v v=bt×v 其中 t = ⌊ a / b ⌋ t=\lfloor a/b \rfloor t=a/b

证明:存在 k ( 1 ≤ k ≤ a ) k(1 \le k \le a) k(1ka) 使得 ( k × v ) % a = 1 (k \times v) \% a=1 (k×v)%a=1


先证明:对于 k ( 1 ≤ k ≤ a ) k(1 \le k \le a) k(1ka) 不存在 t t t 使得 ( t × v ) % a = ( k × v ) % a (t \times v)\%a=(k \times v)\%a (t×v)%a=(k×v)%a,其中 ( t < k ) (t<k) (t<k)

问题可转化为:证明 不存在 t t t 使得 t % a = k % a t \%a=k\%a t%a=k%a, ( t < k ) (t<k) (t<k)

运用 我今天刚学的 反证法:

t % a = b t\%a=b t%a=b

b ≠ 0 b\neq 0 b=0,则 k = b + m × a , ( m ≠ 1 ) k=b+m\times a,(m\neq1) k=b+m×a(m=1)

所以 m < 1 m<1 m<1 m > a m>a m>a矛盾

b = 0 b=0 b=0,则 t = a t=a t=a

因为 k > t k>t k>t,所以 k > a k>a k>a矛盾

所以,对于 k ( 1 ≤ k ≤ a ) k(1 \le k \le a) k(1ka) 不存在 t t t 使得 ( t × v ) % a = ( k × v ) % a (t \times v)\%a=(k \times v)\%a (t×v)%a=(k×v)%a,其中 ( t < k ) (t<k) (t<k)


因为:对于 k ( 1 ≤ k ≤ a ) k(1 \le k \le a) k(1ka) 不存在 t t t 使得 ( t × v ) % a = ( k × v ) % a , ( t < k ) (t \times v)\%a=(k \times v)\%a,(t<k) (t×v)%a=(k×v)%a,(t<k)

所以, ( k × v ) % a (k \times v)\%a (k×v)%a 包含了 0 ∼ a − 1 0 \sim a-1 0a1 的所有数。

所以, ( k × v ) % a (k \times v)\%a (k×v)%a 包含 1 1 1

所以 ,存在 k ( 1 ≤ k ≤ a ) k(1 \le k \le a) k(1ka) 使得 ( k × v ) % a = 1 (k \times v) \% a=1 (k×v)%a=1

所以,存在 k ( 1 ≤ k ≤ a ) k(1 \le k \le a) k(1ka) 使得 k × b − ⌊ ( k × b ) / a ⌋ = 1 k \times b-\lfloor (k\times b)/a \rfloor=1 k×b⌊(k×b)/a=1

所以,当 x = − ⌊ ( k × b ) / a ⌋ , y = k x=-\lfloor (k\times b)/a \rfloor,y=k x=⌊(k×b)/a,y=k 时, a × x + b × y = gcd(a,b) = 1 a \times x + b \times y = \text{gcd(a,b)}=1 a×x+b×y=gcd(a,b)=1

s t 3 : a ≠ 0 , gcd ( a , b ) ≠ 0 st_3:a \neq 0,\text{gcd}(a,b)\neq0 st3a=0,gcd(a,b)=0

g = gcd ( a , b ) g= \text{gcd}(a,b) g=gcd(a,b)

x , y x,y x,y 为当 { a = a / g , b = b / g } \{ a=a/g,b=b/g \} {a=a/g,b=b/g} 时的解,这里 gcd ( a / g , b / g ) = 1 \text{gcd}(a/g,b/g)=1 gcd(a/g,b/g)=1,所以可以使用 s t 2 st_2 st2

因为, a g × x + b g × y = g \frac{a}{g}\times x+\frac{b}{g}\times y=g ga×x+gb×y=g

所以, a × x + b × y = g = gcd(a,b) a \times x + b \times y =g= \text{gcd(a,b)} a×x+b×y=g=gcd(a,b)

至此,证毕。

下面是我用我的结论写出来的代码,缺点是时间复杂度是 O ( n ) O(n) O(n) 的,这个日后在优化吧。

在代码中我只打开了 x , y x,y x,y 的打印,想看的详细一点的请自行解开封印

我的 a , b a,b a,b 是随机的,可以改为自己输入。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline ll Rand_1(ll x,ll y){
	return (rand()*rand())%(y-x+1)+x;
}
inline Rand(ll x,ll y){
	if(x>0)return Rand_1(x,y);
	if(y<0)return -Rand_1(-y,-x);
	ll op=Rand(1,2);
	if(op==1)return Rand_1(0,y);
	else return -Rand_1(1,-x);
}
inline pair<ll,ll>peishu(ll a,ll b){
	if(a==0){
		if(b<0)return{0,-1};
		if(b>0)return{0,1};
	}
	if(a<0){
		pair<ll,ll>res=peishu(-a,b);
		res.first*=-1;
		return res;
	}
	if(b<0){
		pair<ll,ll>res=peishu(a,-b);
		res.second*=-1;
		return res;
	}
	if(a==1)return{-(b-1),1}; 
	if(a==b)return{1,0};
	if(a>b){
		pair<ll,ll>res=peishu(b,a);
		swap(res.first,res.second);
		return res;
	}
	if(b%a==0)return{1,0};
	if(__gcd(a,b)>1){
		ll g=__gcd(a,b);
		pair<ll,ll>res=peishu(a/g,b/g);
		return res;
	}
	ll v=b-(b/a)*a;
	for(ll k=1;k<=a;k++)if(v*k%a==1)return{-(b*k/a),k};
}
signed main(){
	srand(time(0));
	ios::sync_with_stdio(false);
	for(ll q=1;q<=100000;q++){
//		cout<<endl<<"q = "<<q<<endl;
		cout<<endl;
		ll k=Rand(1,100);
		ll a=k*Rand(-1000,1000),b=k*Rand(-1000,1000);
//		ll a,b;cin>>a>>b;
		cout<<"a = "<<a<<"   b = "<<b<<endl;
		pair<ll,ll>res=peishu(a,b);
		ll x=res.first,y=res.second;
		cout<<"x = "<<x<<"   y = "<<y<<endl;
//		cout<<"a*x = "<<a*x<<"   b*y = "<<b*y<<"   a*x+b*y = "<<a*x+b*y<<"   gcd(a,b) = "<<abs(__gcd(a,b))<<endl;
		if(a*x+b*y!=abs(__gcd(a,b)))break;
	}
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值