题目描述
求解X 和 Y 的最大公约数f(x, y)
解法一:
使用辗转相除法,f(x, y) = f(y, x % y), x 和 y 数字偏大则取模运算偏多而开销大
解法二:相减法,f(x,y) = f(x-y,y) , (x > y)。 可以解决取模开销问题,但是相对减法则迭代次数偏多
解法三:结合以上两种优势,如果每次递归求解时
1、同为偶数,则f(x,y) = 2 * f(x, y)
2、x奇数y偶数,则f(x,y) = f(x>>1, y)
3、y奇数x偶数,则f(x,y) = f(x,y>>1)
4、同为奇数,则f(x, y) = f(x-y, y), x>y
package chapter_2_binary;
import java.util.Scanner;
/**
* @author LiangGe
*
* 求解x和y的最大公约数
*
*/
public class question_2_7_1 {
/**
* @param x
* @param y
* @return
*
* 直接使用相除法
*
*/
public static long gcd(long x, long y) {
return (y == 0) ? x : gcd(y, x % y);
}
/**
* @param x
* @param y
* @return
* x和y的最大公约数同时也是 x-y 和 y的最大公约数
* 使用相减法,可以避免数字很大时候的除法运算
*
*/
public static long bigGcd(long x, long y) {
if(x < y) {
return bigGcd(y, x);
} else if(y == 0) {
return x;
} else {
// 迭代次数太多,如果10000000 1 则计算效率降低
return bigGcd(x - y, y);
}
}
/**
* @param x
* @param y
* @return
*
* 结合以上两种方式的优势
* 根据x和y的奇偶性质,简化计算方式
*
*/
public static long bigGcd2(long x, long y) {
if(x < y) {
return bigGcd2(y, x);
} else if(y == 0) {
return x;
} else {
if(x % 2 == 0) {
if(y % 2 == 0) {
// 如果x和y都是偶数,则gcd(x,y) = 2*(x/2,y/2)
return 2 * bigGcd2(x>>1, y>>1);
} else {
return bigGcd2(x>>1, y);
}
} else {
if(y % 2 == 0) {
return bigGcd2(x, y>>1);
} else {
return bigGcd2(x - y, y);
}
}
}
}
public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
long num = scanner.nextLong();
scanner.nextLine();
while (num-- > 0) {
long x = scanner.nextLong();
long y = scanner.nextLong();
System.out.println("(" + x + ", " + y + ") 最大公约数 = " + gcd(x, y));
System.out.println("(" + x + ", " + y + ") 最大公约数 = " + bigGcd(x, y));
System.out.println("(" + x + ", " + y + ") 最大公约数 = " + bigGcd2(x, y));
}
}
}