数论学习笔记:扩展欧几里得

欧几里得算法

欧几里得算法:gcd(a,b)=gcd(a,a mod b)

证明:
令a=kb+r,d=gcd(a+b)
下证d=gcd(b,r):
∵ d ∣ a , d ∣ b \because d|a ,d|b da,db
∴ r = − k b + a \therefore r=-kb+a r=kb+a ∴ d ∣ r \therefore d|r dr
∴ d 为 r , b 公 约 数 \therefore d为r,b公约数 drb
假设d不是b,r的最大公约数
那么一定存在大于d的数p为b,r最大公约数
∴ p ∣ b , p ∣ r \therefore p|b,p|r pb,pr
又 ∵ a = k b + r 又\because a=kb+r a=kb+r
∴ p ∣ a \therefore p|a pa
又 ∵ d 为 a , b 最 大 公 约 数 , d < p 又\because d为a,b最大公约数,d<p dabd<p
∴ 与 原 命 题 矛 盾 , 故 d 为 b , r 最 大 公 约 数 \therefore 与原命题矛盾,故d为b,r最大公约数 dbr

我们可以用来求最大公约数gcd(a,b)
用递归不断迭代,直到边界条件b=0后回溯。

inline int gcd(int a,int b)
{
    
    
	return b==0?a:gcd(b,a%b);
}

扩展欧几里得算法

首先介绍裴蜀定理(Bezout定理)
对于任何整数a,b,d=gcd(a,b),那么关于x,y的线性不定方程:当且仅当c是d倍数时,a*x+b*y=c有解(可能多个解)

证明如下:
我们使用数学归纳法证明。
递归奠基:
在欧几里得算法中,最后的边界条件是b=0,那么肯定存在x=1,y=0使得 1 × 0 + 0 × 0 = g c d ( a , 0 ) 1\times0 +0\times0=gcd(a,0) 1×0+0×0=gcd(a,0)
当b>0时
∵ g c d ( a , b ) = g c d ( b , a m o d    b ) \because gcd(a,b)=gcd(b,a\mod b) gcd(a,b)=gcd(b,amodb)
∴ b × x + ( a m o d    b ) × y = g c d ( b , a m o d    b ) \therefore b\times x+(a\mod b)\times y=gcd(b,a\mod b) b×x+(amodb)×y=gcd(b,amodb)
又 ∵ a m o d    b = b x + ( a − ⌊ a b ⌋ × b ) y = a y + b ( x − ⌊ a b ⌋ y ) 又\because a\mod b=bx+(a-\lfloor \frac{a}{b}\rfloor \times b)y=ay+b(x-\lfloor\frac{a}{b}\rfloor y) amodb=bx+(aba×b)y=ay+b(xbay)
∴ 令 x ′ = y , y ′ = x − ⌊ a b ⌋ y \therefore 令x^{'}=y,y^{'}=x-\lfloor \frac{a}{b} \rfloor y x=y,y=xbay
∴ a x ′ + b y ′ = g c d ( a , b ) \therefore ax^{'}+by^{'}=gcd(a,b) ax+by=gcd(a,b)
证毕。
通过这种递归的方法我们发现同时也给出x,y的计算方法即扩展欧几里得算法,我们就可以去求ax+by=gcd(a,b)的一组特解了。
如果ax+by=c,其中c是d=gcd(a,b)的倍数,那么先求ax+by=d,在将解出的特解乘上 c d \frac {c}{d} dc
代码实现;

inline int exgcd(int a,int b,int& x,int& y)//传回去
{
    
    
	if(b==0)
	{
    
    
		x=1;y=0;
		return a;
	}
	int d=exgcd(b,a%b,x,y);
	int t=x-a/b*y;
	x=y;
	y=t;
	return d;//返回最大公约数 
}

下面是一些推论:
1.ax+by=1 有解,当且仅当gcd(a,b)=1,即a,b互质。
2.若gcd(a,b)=1, a x ≡ c ( m o d    b ) ax\equiv c(\mod b) axc(modb) 等价于ax+by=c,在[0,b-1]上有唯一解;
若gcd(a,b)=d,则上面的方程在[0, b d \frac{b}{d} db-1]上有唯一解。
那么用这个我们就可以求最小非负整数解了!

下面来一道例题
传送门luoguP1516

定理1:对于ax+by=c,如果c为gcd(a,b)的倍数时,那么方程有无数多个整数解,否则不存在整数解。(和上面一样)
定理2;若不定方程有解,且特解为 x 0 , y 0 x_0,y_0 x0,y0,那么方程的解可以表示为;
x = x 0 + b d t , y = y 0 − a d t , t ∈ Z x=x_0+\frac{b}{d}t,y=y_0-\frac{a}{d}t,t\in Z x=x0+dbt,y=y0dat,tZ

回到这道题,容易得到(x+m*t)-(y+n*t)=kL, k ∈ N k\in N kN
化简亿下,得到(n-m)t+kL=x-y
令A=n-m,B=x-y
则At+kL=B
这不就是对于t和k的不定方程吗?用拓展欧几里得可得到一组特解,在用上面的便可求出最小非负整数解了,PS:注意是否为负

#include<iostream>
using namespace std;
#define ll long long 
ll x,y,m,n,l,r=0;
ll exgcd(ll a,ll b,ll &x,ll &y)
{
    
    
	if(b==0)
	{
    
    
		x=1;
		y=0;
		return a;
	}
	r=exgcd(b,a%b,x,y);
	ll t=x;
	x=y;
	y=t-a/b*y;
	return r;
}
int main(){
    
    
	scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&l);
	ll A=n-m,B=x-y;
	if(A<0)
	{
    
    
		A=-A;
		B=-B;
	}
	exgcd(A,l,x,y);
	int d=l/r;
	if(B%r!=0)
		cout<<"Impossible";
	else cout<<((x*(B/r))%d+d)%d;
}

Guess you like

Origin blog.csdn.net/pigonered/article/details/120838755