求N个数的最大公约数和最小公倍数及Hanks博士问题

一、 题目名称:
求N个数的最大公约数和最小公倍数及Hanks博士问题

二、 题目内容:
1、求N个数的最大公约数和最小公倍数。
2、已知正整数a0,a1,b0,b1,设某未知正整数x满足:
(1) x和a0的最大公约数是a1;
(2) x和b0的最小公倍数是b1。
求x的个数

三、 算法设计:

基本要求:
1.输入需要数据个数N以及数据data[N]
2.检验数据是否符合规范1
3.若符合,分别执行执行求N个数的最大公约数方法以及最小公倍数算法,若不符合,则输出错误。

提高要求
1.输入需要n行数据以及每行的4个数据。
2.判断数据是否符合规范2
3.若符合,执行找x个数的算法,若不符合,则输出错误

基本要求:
在这里插入图片描述
在这里插入图片描述

提高要求:
在这里插入图片描述在这里插入图片描述

四、调试截图:
1.调试输入部分,确保程序能由接收到输入。
在这里插入图片描述
                                              图 1 调试“输入”

2.调试求最大公约数部分,验证方法是否正确。
在这里插入图片描述
                                             图 2 调试“最大公约数”

3 .调试求最小公倍数部分,验证方法是否正确。
在这里插入图片描述
                                           图 3 调试“最小公倍数”

4.调试求x方法,验证方法过程是否正确
在这里插入图片描述
                                            图 4 调试“求x个数”

5.调试数据检验方法,验证方法过程是否正确
在这里插入图片描述
                                                图 5 调试“数据检验”

五、测试结果:
1.结果测试
基本要求:

Data[0]  Data[1]  Data[2]  Data[3]  Data[4]  最大公因数  最小公倍数
    2           6                                                         2                   6 
   36         27           54                                         9                 108
   23         41           37         25                            1               872275
   55         20           35        100        60               5                23100

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

提高要求:

Array[0]  Array[1]  Array[2]  Array[3]  X 的个数
    41           1            96         288            2
    95           1            37        1176           6
    33           3            69          27             0
    42           1            86          24             0

在这里插入图片描述
在这里插入图片描述

若输入数据错误:
在这里插入图片描述

六、遇到的困难及解决方案:
1、报错:cannot make a static reference to the non-static method ManyDivisor(int[],int)from the type Two2
在这里插入图片描述

报错原因:在静态的main方法中调用了动态的ManyDivisor()方法。
解决方法:在方法前 ManyDivisor(data , N)加上new Two().来实现调用
代码:

System.out.println("这"+N+"个数的最大公因数为"+new Two().ManyDivisor(data , N));	

2.不清楚怎么写计算结果不为整数
在这里插入图片描述

解决方法:用a/b == a*1.0/b方法实现结果为整数
代码:

(array[j][3]/array[j][2])!=(array[j][3]*1.0/array[j][2])
(array[j][0]/array[j][1])!=(array[j][0]*1.0/array[j][1])

3、“输入的数据太苛刻了,竟然没有x符合要求”与“满足x的个数为:0”重复了
在这里插入图片描述

解决办法:用if-else语句解决
代码:

if(num==0) {	//没有x符合条件情况
				System.out.println("第"+(j+1)+"行输入的数据太苛刻了,竟然没有x符合要求");
			}else {			//有x符合条件情况
	        	System.out.println("第"+(j+1)+"行满足x的个数为:"+num);
	       	}

七、总结与提高:
总结:这次作业让人回顾基本的算法流程,对代码风格,调试程序,流程图,解决bug能力以及数据结构等有了进一步的认识,在设计算法的时候,需要先把数据结构算法等构思清楚,把每个模块做好,随后在main方法里调用即可。

提高:最大公因数和博士的“逆问题”都有时间复杂度低的算法,可以经过比较之后用效率最高的算法实现。


最后附上源码

import java.util.Scanner;

public class Two {

	public static void main(String[] args) {
		
		/*
		 * 基本要求
		 */
		System.out.println("——————基本要求——————");
		System.out.println("***求N个数的最大公约数与最小公倍数***");
		System.out.println("规定1≤a0,a1,b0,b1≤10000,且0<n≤100");
		System.out.println("请输入N个数,N=");
		Scanner sx = new Scanner(System.in);
		int N = sx.nextInt();	//输入N的值
		System.out.println("请输入"+N+"个数据");
		int data[]=new int[N];	//定义数组
		for(int i=0;i<N;i++)	//输入N个int类型的数据
		{
			data[i]=sx.nextInt();
		}
		//判断语句规范,并执行方法ManyDivisor(),ManyMultiple()方法
		if(DataSpecification1(data,N)==1) {
			//执行求N个数的最大公约数方法
			System.out.println("这"+N+"个数的最大公因数为"+new Two().ManyDivisor(data , N));	
			//执行求N个数的最小公倍数数方法
			System.out.println("这"+N+"个数的最小公倍数为"+new Two().ManyMultiple(data , N));	
		}
		
		
		/*
		 * 提高要求
		 */
		System.out.println("——————提高要求——————");
		System.out.println("***解决Hankson博士的“逆问题”***");
		System.out.println("未知正整数x满足:");
		System.out.println("  x和a0的最大公约数是a1");
		System.out.println("  x和b0的最小公倍数是b1");
		System.out.println("每行数据输入格式为:a0 a1 b0 b1  (ps:中间空格隔开)");
		System.out.println("规定输入数据a0能被a1整除,b1能被b0整除。");
		System.out.println("请输入n*4的数组,行数n=");
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int[][] array = new int[n][4];	//定义n*4数组
		for(int i=0; i<n; i++){		//输入n*4数组的数据
			System.out.println("请输入第"+(i+1)+"行的四个数据");
				array[i][0]=sc.nextInt();	//输入a0
				array[i][1]=sc.nextInt();	//输入a1
				array[i][2]=sc.nextInt();	//输入b0
				array[i][3]=sc.nextInt();	//输入b1
		}
		//判断语句规范,并执行SeekingX()方法
		if(DataSpecification2(array,n)==1) {
			SeekingX(array,n);
		}
		
	}
	
	/*
	 * 数据规范1
	 */
	public static int DataSpecification1(int data[],int N) {
		int leap=1;//判断循环是否提前结束的变量
		for(int j=0;j<N;j++)
		{//1≤a0,a1,b0,b1≤10000 且n≤100
			if(data[j]<0 && data[j]>10000 && N<0 && N>100) {//规定1≤a0,a1,b0,b1≤10000,且0<n≤100 
				System.out.println("输入数据不符合规则,请重新运行程序输入合适数据");//如果不成立,则输入数据不符合规则
				leap=0;
				break;
			}
		}
		return leap;//利用返回值来判断SeekingX方法是否继续进行
		}
		
	/*
	 * 数据规范2
	 */
	public static int DataSpecification2(int array[][],int n) {
		int leap=1;//判断循环是否提前结束的变量
		for(int j=0;j<n;j++)
		{
			if((array[j][3]/array[j][2])!=(array[j][3]*1.0/array[j][2]))//输入数据保证a0能被a1整除,b1能被b0整除。
				if((array[j][0]/array[j][1])!=(array[j][0]*1.0/array[j][1]))
				{
					System.out.println("输入数据不符合规则,请重新运行程序输入合适数据");//如果不成立,则输入数据不符合规则
					leap=0;
					break;
				}
			
		}
		return leap;//利用返回值来判断SeekingX方法是否继续进行

	}
	
	/*
	 * 穷举法求最大公约数
	 */
	public static int Divisor (int a,int b) //自定义函数求两数的最大公约数
	{
	    int  temp;          //定义义整型变量
	    temp=(a>b)?b:a;    //采种条件运算表达式求出两个数中的最小值
	    while(temp>0)     
	    {
	       if (a%temp==0&&b%temp==0) //只要找到一个数能同时被a,b所整除,则中止循环
	          break;    
	       temp--;      //如不满足if条件则变量自减,直到能被a,b所整除
	    }
	  return (temp); 	//返回满足条件的数到主调函数处
	}
	
	/*
	 * 递归调用求n个数的最大公因数
	 */
	public int ManyDivisor(int[] data,int length)
	{
		//第N个数和[其余N-1个数的最大公约数]的公约数,求第N-1个数和[其余N-2个数的最大公约数]的公约数…………如此递归下去,直到N值为1,这时停止递归,返回元素值
		if (1 == length) {
			return data[0];
		}
	 	else {
	 		return Divisor(data[length - 1], ManyDivisor(data, length - 1));
	 	}
	}
	
	/*
	 * 穷举法求最小公倍数
	 */
	public static int Multiple (int a,int b)
	{
	  int p,q,temp;
	  p=(a>b)?a:b;   /*求两个数中的最大值*/
	  q=(a>b)?b:a;  /*求两个数中的最小值*/
	  temp=p;      /*最大值赋给p为变量自增作准备*/
	  while(true)   /*利用循环语句来求满足条件的数值*/
	  {
	    if(p%q==0)
	      break;  /*只要找到变量的和数能被a或b所整除,则中止循环*/
	    p+=temp;   /*如果条件不满足则变量自身相加*/
	  }
	  return  (p);
	}
	
	/*
	 * 递归调用求n个数的最小公倍数
	 */
	public int ManyMultiple(int[] data,int length)
	{
		//第N个数和[其余N-1个数的最小公倍数]的公约数,求第N-1个数和[其余N-2个数的最小公倍数]的公倍数…………如此递归下去,直到N值为1,这时停止递归,返回元素值
		if (1 == length) {
			return data[0];
		}
		else {
			return Multiple(data[length - 1], ManyMultiple(data, length - 1));
		}
	}

	/*
	 * 求满足条件的x的个数
	 */
	public static void SeekingX(int array[][],int N)
	{
		for(int j=0;j<N;j++)//利用循环,求出每一组数据x的个数
		{
			int x=0;	
			int num=0;	//定义符合x的个数为num
			for(int i=1;i<10000;i++){
	            if(Divisor(i,array[j][0])==array[j][1]) {//divisor方法为求俩个数的最大公约数
	                x=i;//如果x和a0的最大公约数是a1,满足第一条规则,再用这个x来验证第二条规则
	                if(Multiple(x,array[j][2])==array[j][3]) {//multiple方法为求俩个数的最小公倍数
	                	num++;//如果x和b0的最小公倍数是b1,满足第二条规则,记录x个数的num变量++
	                	System.out.println("第"+(j+1)+"行符合规则的x="+x);
	                }
	            }
			}
			if(num==0) {	//没有x符合条件情况
				System.out.println("第"+(j+1)+"行输入的数据太苛刻了,竟然没有x符合要求");
			}else {			//有x符合条件情况
	        System.out.println("第"+(j+1)+"行满足x的个数为:"+num);
	        }
		}	
	}
	
}
	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值