【概念】
1.公约数:有 k 个非零整数 ,若
,s.t.
,则称 d 为
的公约数。
2.最大公约数:公约数中最大的一个数称为最大公约数,记为:
注:
① 最大公约数一定是存在的,其最小值为 1。
② 当 GCD=1 时,则称这些数是互质的。
③ 公约数一定是最大公约数的约数。
3.公倍数:有 k 个非零整数 ,若
,s.t.
,则称 d 为
的公倍数。
4.最小公倍数:公倍数中最小的一个数称为最小公倍数,记为:
注:公倍数一定是最小公倍数的倍数。
【欧几里德算法】
欧几里德算法又称为辗转相除法,用于求两个数的最大公约数,其原理为:,即:
1.实现
int GCD(int x,int y){
if(y==0)
return x;
else
return GCD(y,x%y);
}
2.二进制算法
1)原理
为提高效率,可将欧几里德算法进行优化,通过不断去除因子 2 来降低常数。
- 当
时,
- 当 x、y 均为偶数时,
- 当 x 为偶数,y 为奇数时,
- 当 x 为奇数,x 为偶数时,
2)实现
int GCD(int x,int y){
if(x==0)
return y;
if(y==0)
return x;
int i,j;
for(i=0;!(x&1);i++)//约去2
x>>=1;
for(j=0;!(y&1);j++)//约去2
y>>=1;
if(i>j)
i=j;
while(true){
if(x<y){//若x<y,交换两数,保证大数在前
x^=y;
y^=x;
x^=y;
}
if((x-=y)==0)//辗转减
return y<<i;
while(!(x&1))//约去2
x>>=1;
}
}
【扩展欧几里德算法】
扩展欧几里德算法是在已知 x、y 时,求解一组 a、b,使得
1.过程分析
设
① 当 时,
,此时
② 当 x>y>0 时
设 ,
由于
故
即
因此
易得
这样就得到了求解 、
的方法:
、
的值基于
、
由于 GCD 不断的递归求解,因此一定会在某时 ,结束递归,从而得出 a、b 的值。
注: x-[x/y]*y 即为 mod 运算,[x/y] 代表取小于 x/y 的最大整数。
2.实现
int Extended_GCD(int x,int y,int &a,int &b){
if(y==0){
a=1;
b=0;
return x;
}
int gcd=Extended_GCD(b,a%b,y,x);
b-=a*(x/y);
return gcd;
}
int main(){
//形如 ax+by=GCD(x,y)
int x,y,a,b;
cin>>x>>y;
int gcd=Extended_GCD(x,y,a,b);
cout<<"GCD="<<gcd<<endl;
cout<<"a="<<a<<",b="<<b<<endl;
return 0;
}
【最小公倍数】
定理:a、b 两个数的最小公倍数乘以它们的最大公约数等于 a 和 b 本身的乘积。
即:
在求 LCM 时,如果将 LCM 写成 a*b/GCD(a,b),a*b 可能会溢出,正确的方法应该是先除后乘,即:a/GCD(a,b)*b
int GCD(int x,int y){
return !y?x:GCD(y,x%y);
}
int LCM(int x,int y){
return x/GCD(x,y)*y;
}