欧几里得算法
欧几里得算法: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;
}