java 求N个数的最大公约数和最小公倍数,及其逆问题:Hanks问题

基本要求:求N个数的最大公约数和最小公倍数。用C或C++或java或python
语言实现程序解决问题。
1.程序风格良好(使用自定义注释模板)
2.提供友好的输入输出,并进行输入数据的正确性验证。
提高要求:
Hanks博士是BT ( Bio-Tech,生物技术)领域的知名专家,他的儿子名叫
Hankson。现在,刚刚放学回家的Hankson正在思考一个有趣的问题。
今天在课堂上,老师讲解了如何求两个正整数c1和c2的最大公约数和最小公
倍数。现在Hankson认为自己已经熟练地掌握了这些知识,他开始思考一- 个“求
公约数"和“求公倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数
a0,a1,b0,b1,设某未知正整数x满足:
1、x 和a0的最大公约数是a1;
2、x和b0的最小公倍数是b1。
Hankson的“逆问题"就是求出满足条件的正整数x。但稍加思索之后,他发现这
样的x并不唯- - ,甚至可能不存在。因此他转而开始考虑如何求解满足条件的x
的个数。请你帮助他编程求解这个问题。
输入格式
输入第一行为一个正整数n,表示有n组输入数据。接下来的n行每行-组输入
数据,为四个正整数a0, a1, bo, b1,每两个整数之间用一个空格隔开。输入
数据保证a0能被a1整除,b1能被b0整除。
输出格式
输出共n行。每组输入数据的输出结果占一行,为一个整数。
对于每组数据:若不存在这样的x,请输出0;
若存在这样的x,请输出满足条件的x的个数;
样例输入
2
41196288
95 1371776
样例输出
6
2

一.基本要求:
1.N个数最大公因数:
先判断输入数字的正确性
先运用欧几里得算法计算出输入的前两个数字的最大公因数,然后用着个公因数与下个数字进行欧几里得算法,依次循环计算到所输入数字结束。
2.N个数最小公倍数:
运用公式法,最小公倍数=两个数的乘积÷两个数字的最大公因数。
先进行欧几里得到输入的前两个数的最大公因数,然后套公式计算出他们的最小公倍数,再用这个最小公倍数与下一个输入的数字进行欧几里得算法计算出最大公因数,再依次循环计算出最小公倍数。
下图为程序流程图

程序流程图

具体代码:

在这里插入代码片/**
 * @className: Number
 * @Description: 父类,用于存放数值和判读输入数值的正确性
 *  */
public class Number {
	public Scanner in = new Scanner(System.in);
	String [] str = null;
	int [] i;
	int pd = 1;
	
	public void addNum() {	/*添加数字函数*/
		System.out.println("请输入数字,回车表示结束!");
		str = in.nextLine().split(" ");/*输入时,用空格隔开,回车结束输入*/
		i = new int[str.length];
		for (int k = 0; k<str.length;k++) {
			i[k] = Integer.valueOf(str[k]);/*运用Integer.valueOf方法
											将string数组中的每一个值
			 								赋到int数组中*/
		}
		in.close();
	}	
	
	public void judge() {
		for (int t = 0; t<i.length; t++) {
			if (i[t] ==0) {
				pd =0;		/*pd为0,
							表示所输入数据中有0*/
				break;
			}	
		}
	}
	
	public  static void main (String[] args) {
		CommonMultiple cm =new CommonMultiple();
		cm.addNum();
		cm.judge();//判断输入数据的正确性,不能含有零
		if (cm.pd ==1)	{
			System.out.println("最小公倍数为:"+cm.comMult());
		    System.out.println("最大公约数为:"+cm.Gcd());
		    }
		else 	
			System.out.println("数字中不能含有零");
	}

}
``/**
 * @className: CommonMultiple
 * @Description: 继承CommonDivisor,用于计算最小公倍数
 */
public class CommonMultiple extends CommonDivisor{

	public int multiple(int a, int b) {/*计算两个值得乘积*/
		return a*b;
	}

	public int comMult() {/*公式法计算最小公倍数
	 					两个数的乘积 = 这两个数的最大公因数
	 					与最小公倍数的相乘,所以
	 					最小公倍数 =两个数的乘积 ÷ 最大公因数*/
		int answer = 0;
		if(i.length!=1) {
			int x = gcd(i[0],i[1]);
			int y = multiple(i[0], i[1]);
			answer = y/x;
			for (int o = 2;o < (i.length);o++) {/*循环计算每两个
			 									数字的最小公倍数*/
				x = gcd(answer,i[o]);
				y = multiple(answer, i[o]);
				answer = y/x;
			}
		}
		else
			answer = i[0];
		return answer;
	}
}

/**
 * @className: CommonDivisor
 * @Description: 继承Number,求最大公因数
 */
public class CommonDivisor extends Number{
	public int gcd(int  a, int  b) { /*欧几里得算法*/
		int t,x,y; 					// 用于求最大公约数
    	x = a;   
    	y = b;  
		if (i.length !=1) {
			if (x!=y&&y!=0)  {
				if (y<x) {
					t = x;
					x = y;
					y = t;  
				}  
				while(y!=0)  {		//求最大公约数x
					t = x%y;
					x = y;
					y = t;
    			}
    		}
    	}
		else if (i.length==1)
			x = i[0];
		return x;
	}
	
	public int Gcd() {	/*对每一个从欧几里得算法中算出
	 					的最大公约数一次与下一个输入的
	 					数字进行欧几里得算法,直到遍历
	 					结束,可以求N个数的最大公约数*/
		int answer;
		if(i.length!=1) {	/*当数组长度不为1时,进行循环遍历计算
		 					将上两个i数组中的数字的最大公因数与下一个数字
		 					进行欧几里得算法。*/
			answer = gcd(i[0],i[1]);
			for (int j = 2;j<i.length;j++) {
				answer = gcd(answer,i[j]);
			}
		}
		else 			/*数据长度为1时,*/
			answer = i[0];
		return answer;
	   }
	}

运行结果:
在这里插入图片描述在这里插入图片描述

二.提高要求:
算法思路:
套用最大公因数与最小公倍数的函数,利用双循环,外层循环进行层数的变更,
内层循环进行判定:如果j与a0的最大公因数=a1并且j与b0的最小公倍数=b1
个数x加一,如果j达到最大值,把个数x赋给数组pp然后充值x,进行下一层的循环
核心代码实现:

public void judge() {		/*判断所输入数据中符合要求的数字个数
	 							并且进行输出*/
		int n = 0;				
		int x = 0;
		int [] pp = new int[k];
		/*利用双循环,外层循环进行层数的变更,
		 内层循环进行判定:如果j与a0的最大公因数=a1并且j与b0的最小公倍数=b1
		 个数x加一,如果j达到最大值,把个数x赋给数组pp然后充值x,进行下一层的循环*/
		for (int i = 0;i<k;i++ ) 
			for (int j = num[i][1];j<=num[i][3];j++) {
				if(gcd(num[i][0],j)==num[i][1]&&(gbs(num[i][2],j)==num[i][3])) {
				x++;
				}
				if (j == (num[i][3])) {
					pp[n] = x; //把获得x赋到pp数组中
					x = 0;	   //重置
					n++;
				}				
		}
		for (int m:pp)
		System.out.println(m);//输出每行符合条件数字的个数
	}

输入数组及计算最大公因数与最小公倍数的方法代码:

public class Text {
	public Scanner in = new Scanner(System.in);
	private int[][] num;//二维数组,存放输入数字
	int k;
	public void setNumber() {	/*建立数字输入数组*/
		k = in.nextInt();		/*输入几行数字的判断,*/
		num = new int[k][4];
		for (int l = 0;l<k;l++)	/*循环赋值*/
			for(int j =0 ; j<4;j++) {
				num[l][j] = in.nextInt();
			}
	}

	public int gcd(int  a, int  b) { /*欧几里得算法*/
		int t,x,y; 					// 用于求最大公约数
    	x = a;   
    	y = b;  
		if (x!=y&&y!=0)  {
			if (y<x) {
				t = x;
				x = y;
				y = t;  
			}  
			while(y!=0)  {		//求最大公约数x
				t = x%y;
				x = y;
				y = t;
			}
    	}
		return x;
	}

	public int gbs(int a, int b) {/*最小公倍数算法,公式法*/
		int answer;
		answer = (a*b)/gcd(a,b);
		return answer;
	}
	
		public void judge() {		/*判断所输入数据中符合要求的数字个数
		 							并且进行输出*/
			int n = 0;				
			int x = 0;
			int [] pp = new int[k];
			/*利用双循环,外层循环进行层数的变更,
			 内层循环进行判定:如果j与a0的最大公因数=a1并且j与b0的最小公倍数=b1
			 个数x加一,如果j达到最大值,把个数x赋给数组pp然后充值x,进行下一层的循环*/
			for (int i = 0;i<k;i++ ) 
				for (int j = num[i][1];j<=num[i][3];j++) {
					if(gcd(num[i][0],j)==num[i][1]&&(gbs(num[i][2],j)==num[i][3])) {
					x++;
					}
					if (j == (num[i][3])) {
						pp[n] = x; //把获得x赋到pp数组中
						x = 0;	   //重置
						n++;
					}				
			}
			for (int m:pp)
			System.out.println(m);//输出每行符合条件数字的个数
		}

主函数测试代码:

public static void main(String[] args) {
		// TODO Auto-generated method stub
		Text t = new Text();
		t.setNumber();
		t.judge();
	}

程序运行结果:
在这里插入图片描述
总结:
现阶段还是个java小白。第一篇csdn博客,写的马马虎虎,主要是记录老师上课布置的练习题,我的提高要求中核心部分还是不够完善,循环次数太多,时间复杂度太大,希望有大佬可以指点一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值