求多个正整数的最大公约数和最小公倍数的三种算法

第一种:分解质因数法

import java.util.HashSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
import java.util.Scanner;

/*
 *	@topic:多个正整数的最大公约数和最小公倍数——分解质因数法
 */
/*
 *  756 = 2*2*3*3*3*7
 *	504 = 2*2*2*3*3*7
 *	630 = 2*3*3*5*7
 *	2226 = 2*3*7*53
 *	最大公约数为4个数的公因子相乘:2*3*7 = 42
 *	最小公倍数为4个数不重复因子相乘:2*2*2*3*3*3*5*7*53 = 400680
 */
public class GcdLcm {
	static int[] a;//存放正整数
	static int n;//正整数个数
	static int[] prime = new int[1000];//素数表
	static HashSet<Integer> qf = new HashSet<Integer>();//存放所有因子
	static HashMap<Integer, Integer> df = new HashMap<Integer, Integer>();//存放重复因子及其个数

	public static void main(String[] args) {
		// System.out.println("Hello Landor!");
		for (int i = 1, j = 0; j < 1000; i++) {
			if (isPrime(i))
				prime[j++] = i;
		}// 建立素数表
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		a = new int[n];
		for (int i = 0; i < n; i++)
			a[i] = sc.nextInt();
		calculate();
		System.out.println("最大公约数为:" + getGcd());
		System.out.println("最小公倍数为:" + getLcm());
	}

	public static void calculate() {//依次将每个正整数进行因数分解:756 = 2*2*3*3*3*7
		int i, j, count = 0;
		for (i = 0; i < n; i++) {
			int m = a[i];
			for (j = 0; j < 1000 && m > 1; j++) {
				Integer key = new Integer(prime[i]);
				while (m % prime[j] == 0) {
					m /= prime[j];
					qf.add(key);//将此因数放进HashSet中(会自动去重)
					count++;
				}
				if (count > 0) {
					if (df.get(key) == null) {//如果此因数没有出现过,则直接将因数及其个数放入HashMap中
						df.put(key, new Integer(count));
					} else if (df.get(key).intValue() < count) {
						df.remove(key);//如果出现此因数的个数比hashmap中的个数大,则删除后将新的个数添加
						df.put(key, new Integer(count));
					}
				}
				count = 0;
			}
		}
	}

	public static int getGcd() {
		int gcd = 1, i, j;
		Iterator<Integer> it = qf.iterator();
		while (it.hasNext()) {//遍历每个qf中的因数,若为公因数则与gcd相乘
			i = it.next().intValue();
			for (j = 0; j < n; j++) {
				if (a[j] % i != 0)//不是公因数
					break;
			}
			if (j == n)
				gcd *= i;
		}
		return gcd;
	}

	public static int getLcm() {
		int lcm = 1;
		//System.out.println(df);
		for (Map.Entry<Integer, Integer> e : df.entrySet())
			lcm *= (int) Math.pow((double) e.getKey().intValue(), (double) e
					.getValue().intValue());//遍历HashMap中的Key和Value,将Key的Value次方与lcm相乘
		return lcm;
	}

	public static boolean isPrime(int n) {// 判断素数
		int i, step = 4, s = (int) Math.sqrt((double) n + 0.01);
		if (n < 1)
			System.exit(1);
		if (n == 2 || n == 3)
			return true;
		if (n == 1 || n % 2 == 0 || n % 3 == 0)
			return false;
		for (i = 5; i <= s; i += step) {
			if (n % i == 0)
				break;
			step ^= 6;
		}
		return i > s;
	}
}
/* 测试实例:
4
756
504
630
2226
最大公约数为:42
最小公倍数为:400680
*/

 

第二种:辗转相除递推法

import java.util.Scanner;

/*
 *	@topic:多个正整数的最大公约数和最小公倍数——辗转相除递推法
 */
/*
 *  先求gcd:
 *	(756,504):756%504 = 252 ,504%252 = 0 ,所以(756,504)=252
 *	(630,252):630%252 = 126 ,252%126 = 0, 所以(630,252)=126
 *	(2226,126):2226%126 = 84,126%84 = 42,84%42=0,所以(2226,126)=42
 *	所以4个数的最大公约数为:(756,504,630,2226)=42
 *	再求lcm:
 *	[756,504]=756*504/252=1512
 *	[1512,630]=1512*630/126=7560   注意,此处的126和上面所求126没有关系,这里的126是需要求gcd(1512,630)得到的
 *	[7560,2226]=7560*2226/42=400680
 *	所以4个数的最小公倍数为:[756,504,630,2226]=400680
 */

public class GcdLcm1 {
	static int[] a;// 存放正整数
	static int n;// 正整数个数

	public static void main(String[] args) {
		// System.out.println("Hello Landor!");
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		a = new int[n];
		for (int i = 0; i < n; i++)
			a[i] = sc.nextInt();
		System.out.println("最大公约数为:" + getGcd());
		System.out.println("最小公倍数为:" + getLcm());
	}

	public static int getGcd() {
		int p = a[0];
		for (int i = 1; i < n; i++)
			p = gcd(Math.max(p, a[i]), Math.min(p, a[i]));
		return p;
	}

	public static int getLcm() {
		int lcm = a[0];
		for (int i = 1; i < n; i++)
			lcm *= (a[i] / gcd(Math.max(lcm, a[i]), Math.min(lcm, a[i])));
		return lcm;
	}

	public static int gcd(int x, int y) {
		return (y == 0) ? x : gcd(y, x % y);
	}
}


第三种:逐次想减、相除法

逐次相减是用来求最大公约数的,是辗转相除的一种推广

算法描述:

     先将m个数由大到小排序,再逐次相减修改各元素的值。设排序后相邻的两个数为A、B(A≥B)。再设n=1、2、3.....,各个A同时按下述方法重新赋值:

       如A>n*B ,则A=A-n*B>0,n是满足条件的最大整数,相当于A=A%B;

       如A=B,A不变;

       如A=n*B,n≠1,则A=A-(n-1)*B,即取A=B,A不能小于1;

   例如:求最大公约数(756,504,630,2226)

   ①4个数排序,再从左到右逐次相减:

           (756,504,630,2226)=(2226,756,630,504)=(2226-2*756,756-630,630-504,504)=(714,126,126,504)

   ②再排序,逐次相减:

           (714,126,126,504)=(714,504,126,126)=(210,504-3*126,126,126)=(210,126,126,126)

   ③再排序,逐次相减:

            (210,126,126,126)=(84,126,126,126)=(126,126,126,84)=(126,126,42,84)=(126,126,84,42)=(126,42,42,42)

                                                            =(126-2*42,42,42,42)=(42,42,42,42)

    此时,四个数相同,完毕,最大公约数为42

   

main()
{
	long a[4]={756,504,630,2226},i,j,t;
	printf("最大公约数:(%ld,%ld,%ld,%ld)\n",a[0],a[1],a[2],a[3]);
	h:for(i=0;i<3;i++)	{
		for(j=i+1;j<=3;j++)
			if(a[i]<a[j]){
				t=a[i];
				a[i]=a[j];
				a[j]=t;
			}
	}
	printf("=(%ld,%ld,%ld,%ld)\n",a[0],a[1],a[2],a[3]);
	if(a[0]==a[3]){
		printf("=%ld\n\n",a[0]);
		exit(0);
	}else{
		for(i=0;i<3;i++){
			if(a[i]%a[i+1]!=0)
				a[i]=a[i]%a[i+1];
			else
				a[i]=a[i+1];
		}
		printf("=(%ld,%ld,%ld,%ld)\n",a[0],a[1],a[2],a[3]);
		goto h;
	}
}

逐次相除:用来求最小公倍数

设有若干数,其中最大的为a,用a的1倍、2倍、3倍、…,除以其余的各数,若第n次恰好都除尽,则此时的n*a即为它们的最小公倍数

这个算法比较SB,就不贴代码了,有兴趣自己写一下。


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 两个正整数a和b的最大公约数可以使用辗转相除法,即:gcd(a, b) = gcd(b, a mod b)。当a mod b = 0时,gcd(a, b) = b。 两个正整数a和b的最小公倍数可以使用lcm(a, b) = a * b / gcd(a, b)。 ### 回答2: 最大公约数(GCD)是指两个或多个整数中能够同时整除它们的最大正整数。最小公倍数(LCM)是指能够同时整除两个或多个整数的最小正整数两个正整数最大公约数和最小公倍数的方法有很多种,下面介绍两种常用的方法。 一种方法是使用辗转相除法。假设要两个正整数a和b的最大公约数和最小公倍数,先用辗转相除法得它们的最大公约数gcd(a, b)。具体步骤如下:用b去除a,得到余数r,如果r等于0,则a就是最大公约数;如果r不等于0,则将a替换为b,b替换为r,然后继续用新的b去除新的a,计算新的余数,直到余数等于0为止。 得最大公约数之后,可以使用最大公约数得最小公倍数的公式:两个数的最小公倍数等于这两个数的积除以它们的最大公约数。即lcm(a, b) = a * b / gcd(a, b)。 另一种方法是因数分解法。先将两个正整数因数分解,然后得它们的公共因子,公共因子的乘积即为最大公约数。接着将两个整数的非公共因子和公共因子相乘,即为最小公倍数。 综上所述,两个正整数最大公约数和最小公倍数可以使用辗转相除法或因数分解法。这些方法简单易懂且易于实现,可以在解相关问题时使用。 ### 回答3: 最大公约数是指两个正整数中能够同时整除的最大的正整数。最小公倍数则是指两个正整数的公共倍数中最小的那个。 最大公约数可以使用欧几里得算法。假设有两个正整数a和b,我们先令r为a除以b的余数,然后将b赋值给a,将r赋值给b。重复以上步骤直到r为0。此时,b即为最大公约数。 最小公倍数可以通过最大公约数来计算。假设有两个正整数a和b,它们的最大公约数为gcd,则最小公倍数为a和b的乘积除以gcd。 例如,72和120的最大公约数和最小公倍数: 根据欧几里得算法: 120除以72的余数为48,将72赋值给120,将48赋值给72; 72除以48的余数为24,将48赋值给72,将24赋值给48; 48除以24的余数为0,最大公约数为24。 最小公倍数为(72 * 120) / 24 = 360。 因此,72和120的最大公约数为24,最小公倍数为360。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值