欧几里得算法
欧几里得算法: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 ∵d∣a,d∣b
∴ r = − k b + a \therefore r=-kb+a ∴r=−kb+a ∴ d ∣ r \therefore d|r ∴d∣r
∴ d 为 r , b 公 约 数 \therefore d为r,b公约数 ∴d为r,b公约数
假设d不是b,r的最大公约数
那么一定存在大于d的数p为b,r最大公约数
∴ p ∣ b , p ∣ r \therefore p|b,p|r ∴p∣b,p∣r
又 ∵ a = k b + r 又\because a=kb+r 又∵a=kb+r
∴ p ∣ a \therefore p|a ∴p∣a
又 ∵ d 为 a , b 最 大 公 约 数 , d < p 又\because d为a,b最大公约数,d<p 又∵d为a,b最大公约数,d<p
∴ 与 原 命 题 矛 盾 , 故 d 为 b , r 最 大 公 约 数 \therefore 与原命题矛盾,故d为b,r最大公约数 ∴与原命题矛盾,故d为b,r最大公约数
我们可以用来求最大公约数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+(a−⌊ba⌋×b)y=ay+b(x−⌊ba⌋y)
∴ 令 x ′ = y , y ′ = x − ⌊ a b ⌋ y \therefore 令x^{'}=y,y^{'}=x-\lfloor \frac{a}{b} \rfloor y ∴令x′=y,y′=x−⌊ba⌋y
∴ 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) ax≡c(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=y0−dat,t∈Z
回到这道题,容易得到(x+m*t)-(y+n*t)=kL, k ∈ N k\in N k∈N
化简亿下,得到(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;
}