欧几里得算法
又称辗转相除法,计算两个整数啊a,b的最大公约数。
算法
设a=q*b+r,其中a,b,q,r都是整数,则gcd(a,b)=gcd(b,r),即gcd(a,b)=gcd(b,a%b).
证明
a = k*b+r,则r = a%b.
设d 是a,b的公约数,那么则有d|a,d|b(d|a表示a能被b除尽,读作“d整除a”),
a = k*b+r,移项得r = a - k*b,左右同时除以d得
rd=ad−k∗bd
r
d
=
a
d
−
k
∗
b
d
,得出结论d|r,因此,d是(b,a%b)的公约数。
同理,设d是a,a%b的公约数,r = a%b,可证得,d也是a,b的公约数。
综上所得,a,b的最大公约数必然能够整除(b,a%b),反之依然,所以他们的最大公约数相等。
int gcd(int a,int b)
{
if(b == 0) return a;
return gcd(b, a%b);//或简化为return b?gcd(a,a%b):a;
}
扩展欧几里得算法
算法
对于不完全为0的非负整数a,b,gcd(a,b)表示a,b的最大公约数,必然存在x,y,使得gcd(a,b) = ax+by.
int exgcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1;
y=0;
return a; //返回最大公约数
}
int r=exgcd(b,a%b,x,y);
int t=x;//一次一更新x和y
x=y;
y=t-a/b*y;
return r;//返回最大公约数
}
用法
求解不定方程
求解 ax+by = c,有解的充分必要条件是c能整除gcd(a,b)。
bool linear_equation(int a,int b,int c,int &x,int &y)
{
int d=exgcd(a,b,x,y); //这一步求出了最大公约数d和ax+by = gcd(a,b)的一组解x和y
if(c%d!=0) //判断ax+by=c有无解,如果无解直接返回false
return false;
x=x*c/d;
y=y*c/d;
return true;
}
若x1,y1为不定整数方程ax+by=c的一组解,则它的解有无数组,任意整数解都可以表示为
x=x1+k∗bgcd(a,b)
x
=
x
1
+
k
∗
b
g
c
d
(
a
,
b
)
y=y1−k∗agcd(a,b)
y
=
y
1
−
k
∗
a
g
c
d
(
a
,
b
)
k = 0,±1,±2,±3······。