1.公约数:有 k 个非零整数 ,若 ,s.t. ,则称 d 为 的公约数。
2.最大公约数:公约数中最大的一个数称为最大公约数,记为:
注:
① 最大公约数一定是存在的,其最小值为 1。
② 当 GCD=1 时,则称这些数是互质的。
③ 公约数一定是最大公约数的约数。
3.公倍数:有 k 个非零整数 ,若 ,s.t. ,则称 d 为 的公倍数。
4.最小公倍数:公倍数中最小的一个数称为最小公倍数,记为:
注:公倍数一定是最小公倍数的倍数。
欧几里德算法又称为辗转相除法,用于求两个数的最大公约数,其原理为:,即:
int GCD(int x,int y){
if(y==0)
return x;
else
return GCD(y,x%y);
}
为提高效率,可将欧几里德算法进行优化,通过不断去除因子 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>=1;
}
}
扩展欧几里德算法是在已知 x、y 时,求解一组 a、b,使得
设
① 当 时,,此时
② 当 x>y>0 时
设 ,
由于
故
即
因此
这样就得到了求解 、 的方法:、 的值基于 、
由于 GCD 不断的递归求解,因此一定会在某时 ,结束递归,从而得出 a、b 的值。
注: x-[x/y]*y 即为 mod 运算,[x/y] 代表取小于 x/y 的最大整数。
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="<
定理: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;
}