目录
-
最大公约数(gcd)
基本原理
gcd(x,x)=x (两个相同数的最大公约数就是这个数本身)
gcd(0,x)=x (0与另一个数x的最大公约数就是x)
gcd(x,y)=gcd(y,x) (x和y的最大公约数与y和x的最大公约数相同)
方法与实现
1.穷举法
从两者中较小者开始递减,直至出现两者公因数
2.短除法
原理:将两数的所有公因子找出来相乘,结果就是两个数的最大公约数
1.f=1
2.利用循环变量i从2开始递增至min(x,y)
每次循环内部判断i是否是x和y的公因子
若是:f*=i;
x/=i;y/=i;
3.返回f;
实现:
int gcd(int x,int y){
int f = 1;
for(int i=2;i<=x && i<=y;i++){
while(m%i==0 && n%i==0){
f*=i;
x/=i;
y/=i;
}
}
return f;
}
3.辗转相除法(欧几里得算法)
原理:
gcd(x,y)=gcd(y,x%y) 其中x>y
1.如果y=0,计算结束,x就是最大公约数
2.否则,计算x除y的余数,让x=y,y=余数
3.回到1
实现
int gcd(int x,int y){
int s;
while(y){//当y不等于0时
s=x%y;
x=y;
y=s;
}
return x;
}
递归实现 :
int gcd(int x,int y){
if(y==0)
return 0;
else
return gcd(y,x%y);
}
4.更相减损法 (九章算术)
原理:(本质与辗转相除相同,当两数差值较大时,辗转相除运算次数更少)
gcd(x,y)=gcd(y,x%y) 其中x>y
辗转相除法取余,更相减损法取差
int gcd(int x,int y){
int s;
while(y){//当y不等于0时
s=(x-y>0)?x-y:y-x;//取两者差的正值
x=y;
y=s;
}
return x;
}
5.Stein算法
当两个数字非常大时,除法运算对于计算机十分复杂,消耗很多CPU时间,Stein算法通过移位运算和加减避免了大量除法运算
原理
gcd(kx,ky)=k*gcd(x,y)
当k与y互质时,gcd(kx,y)=gcd(x,y)
1.计数器c=0;
2.当两数皆为偶数时,同时>>1;c++
当两数一个是奇数,一个是偶数时,偶数>>1;
当两数皆为奇数时,利用更相减损法一次;
3.重复执行步骤2直至两数相等
4.得到的相同的那个数<<c(相当于乘2的c次方),结果即为最大公约数
实现
int stein(int x,int y){
int c = 0;
if (x==0)
return y; //若x为0,y为最大公约数
if (y==0)
return x;
while (y) { //y不等于0时
if(x&1==0){ //x为偶数
x>>1; //x右移一位,相当于除2
if(y&1==0){
y>>=1; //y右移一位
c++; //计数加一
}
}else if(y&1==0) //x为奇数,y为偶数
y>>=1;
else{ //x,y 皆为奇数
int s =(x-y>0)?x-y:y-x;
x=y;
y=s;
}
}
return (x<<c); //返回x左移c位的值
}
递归实现
int stein(int x,int y){
if (x==0)
return y;
if (y==0)
return x;
if( (x&1==0) && (y&1==0) ) //x,y 皆为偶数
return stein(x>>1,y>>1)<<1;
else if( (x&1) && (y&1==0) ) //x为奇数,y为偶数
return stein(x,y>>1);
else if( (x&1==0) && (y&1) ) //x为偶数,y为奇数
return stein(x>>1,y);
else //x,y 皆为奇数
return stein(abs(x-y),y); //abs函数,求整型绝对值。需配合头文件math.h或stdilb.h使用
}
-
最小公倍数(lcm)
基本原理
gcd(x,y) * lcm(x,y) = x*y
方法与实现
1.穷举法
从两数较大者开始递增,直至出现两数的公倍数
2.进阶穷举法
从x, 2*x, 3*x依次倍增,每次判断是否是另一个数的倍数(x>y)
实现
int lcm(int x,int y){
if (x<y){
int s=x;
x=y;
y=s;
}
int i;
for(i=0; ;i++){
if(x*i%y==0)
return i*x;
}
}
3.短除法
4.借助最大公约数求最小公倍数
基本原理:gcd(x,y) * lcm(x,y) = x*y
=>lcm(x,y)=x*y/gcd(x,y)