一、 题目名称:
求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);
}
}
}
}

2655

被折叠的 条评论
为什么被折叠?



