程序设计方法与优化第三次作业

一、问题描述:
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,b0,b1,每两个整数之间用一个空格隔开。输入数据保证a0能被a1整除,b1能被b0整除。
输出格式
输出共n行。每组输入数据的输出结果占一行,为一个整数。
对于每组数据:若不存在这样的x,请输出0;
若存在这样的x,请输出满足条件的x的个数;
样例输入
2
41 1 96 288
95 1 37 1776
样例输出
6
2
二、算法设计思路:
这个问题大致可以分为以下三步解决:
第一步:输入数据,接收从键盘输入的数据,可以定义一个num用于接收有几组输入数据
第二步:判断满足条件的x,并用count保存满足条件的x的个数
第三步:输出数据,输出满足条件的x的个数,即count的值
其中第二步最为关键,可以这样设计算法:由题目我们知道每组输入四个数,分别为四个正整数a0,a1,b0,b1,而判断条件是:
1、 x和a0的最大公约数是a1
2、 x和b0的最小公倍数是b1
由条件2可以很容易的知道如若x和b0的最小公倍数是b1,那么x的取值就并不大于b1,这样我们就能知道x的取值范围,之后用for循环求解即可。
三、调试及测试截屏:
在这里插入图片描述
在这里插入图片描述
一开始输出错误,输出全为1,经检查发现是将count定义在了内层for循环中,使得count每次循环值都被重置,这样每次都会输出1。
将count定义在外层for循环中后再次进行测试:
在这里插入图片描述
在这里插入图片描述

发现输出结果正确。
附源码:
package package1;
import java.util.Scanner;
public class Example {
public static int divisor (int a,int b) /自定义函数求两数的最大公约数/
{
int temp; /定义整型变量/
if(a<b) /通过比较求出两个数中的最大值和最小值/
{ temp=a;a=b;b=temp;} /设置中间变量进行两数交换/
while(b!=0) /通过循环求两数的余数,直到余数为0/
{
temp=a%b;
a=b; /变量数值交换/
b=temp;
}
return (a); /返回最大公约数到调用函数处/
}
public static int multiple (int a,int b) /自定义函数求两数的最小公倍数/
{
divisor ( a, b); /自定义函数返回值类型/
int temp;
temp=divisor(a,b); /再次调用自定义函数,求出最大公约数/
return (a*b/temp); /返回最小公倍数到主调函数处进行输出/
}
public static void main(String[] args)throws Exception {
Scanner sc=new Scanner(System.in);
int num;//定义一个整形变量表示有几组输入数据
System.out.println(“请输入num的值:”);
num=sc.nextInt();//从键盘接收num的值
int[][] arr=new int[num][4];//定义一个二维数组用于存储输入的数据
for(int i=0;i<num;i++)//for循环接收键盘的数据
{
arr[i][0]=sc.nextInt();
arr[i][1]=sc.nextInt();
arr[i][2]=sc.nextInt();
arr[i][3]=sc.nextInt();
if(arr[i][0]%arr[i][1]!=0||arr[i][3]%arr[i][2]!=0)//如果输入数据不满足条件则输出错误体提示并终止程序运行
{
System.out.println(“data error!”);
System.exit(0);
}
}
for(int j=0;j<num;j++)
{
int count=0;//用于存储满足条件的x的个数
for(int x=1;x<=arr[j][3];x++)//for循环找出满足条件的x
{
if(divisor(x,arr[j][0])==arr[j][1]&&multiple(x,arr[j][2])arr[j][3])//满足此条件的x计入count中
{
count++;
}
}
if(count
0)//输出结果,不存在这样的x则输出0,否则正常输出
System.out.println(0);
else
System.out.println(count);
}
sc.close();//关闭输入流
}
}

四、总结:
这次问题的关键解决步骤在于如何判断满足条件的值,而其中最为关键的便是求出x的取值范围,由数学上的定理很容易知道如若x和b0的最小公倍数是b1,那么x的取值就并不大于b1,这样问题就迎刃而解。从这次问题中我还知道了一些数学重要常识的重要性,这有时候对解决问题能提供一个直指问题关键的思路,以后要加强数学思维的锻炼。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值