/******************************/
文件名称:n个正整数的最小公倍数和最大公约数及Hankson问题!
编程语言:Java
编译器:eclipse
完成日期:2019年03月21日
作者:无奈¬_¬`啊
一、求公约数和公倍数
求n个正整数的最大公约数和最小公倍数前,要先有求俩个正整数的最大公约数和最小公倍数的函数。(可以见解我的C++分类里的博客)
有了这个函数之后,理解起来n个数的最大公倍数和最小公倍数就简单多了!
(1)首先,需要一个数组来进行操作,我们可以先利用函数求出前俩个元素的最小公约数和最大公倍数,将其赋值给一个中间变量temp.
(2)利用求出来的temp与数组中的下一个元素作为参数继续求二者的最大公约数和最小公倍数,将其赋值给temp.
(3)重复第二步,直到遍历完数组最后一个元素,最后的最大公约数和最小公倍数就是这n个数的最大公约数和最小公倍数!
求俩个数的最大公约数和最小公倍数的算法:
int gcd(int x,int y) {
if(x<y) { //交换,x为大数,y为小数
temp=x;
x=y;
y=temp;
}
while(y!=0) { //辗转相除法求最大公约数
temp=x%y;
x=y;
y=temp;
}
return x;
}
int lcm(int x,int y) { //求最小公倍数
temp=gcd(x,y);
return ((x*y)/temp);
}
求n个数的最小公倍数和最大公约数的算法:
int ngcd(int a[]) { //求n个数的最大公约数
int i=0; //下标
temp=gcd(a[i],a[i+1]);//先求出前俩个数的最大公约数,并i+2开始准备与第三个数相比
i=i+2;
while(i<a.length) {
temp=gcd(temp,a[i]);
i++;
}
return temp;
}
int nlcm(int a[]) { //求n个数的最小公倍数
int i=0;
temp=lcm(a[i],a[i+1]);
i=i+2;
while(i<a.length) {
temp=lcm(temp,a[i]);
i++;
}
return temp;
}
求n个数的最大公约数和最小公倍数的算法流程图:
二、Hankson问题
Hankson问题:
n组数据,每组数据4个元素(a0,a1,b0,b1);
其中a0可以整除a1,b0可以整除b1;
有一个数x:
x与a0的最大公约数是a1;
x与b0的最小公倍数是b1;
要求求出所有x的个数。
我们可以利用键盘输入n,再用俩个大小为4的数组,一个存放数据,一个存放count(x的个数,因为每组数据都有一个count,所以需要额外一个数组来存放结果)
分析:
x与a0的最大公约数是a1;
x与b0的最小公倍数是b1;
由此知,x的值是在a1与b1之间的数,所以我们只需要让x的初值为a1,然后递增,用循环嵌套if 语句,就可以计算出来x了。
int hankson(int x,int y,int z,int g) {
int s=y; //表示x
if(y>g)
return 0;
else {
while(s>=y&&s<=g) { //通过思考,会发现x的值会在a1和b1之间,即y与g之间
if(gcd(s,x)==y&&lcm(s,z)==g) {
count++; //统计x的数量
s++;
}
else
s++;
}
}
return count;
}
count为x的个数;
算法流程图:
这俩个问题用switch结合在一起!
原代码如下:
package zy;
import java.util.Scanner;
public class Divistor {
static int temp=0;
static int count=0;//计数
static int gcd(int x,int y) {
if(x<y) { //交换,x为大数,y为小数
temp=x;
x=y;
y=temp;
}
while(y!=0) { //辗转相除法求最大公约数
temp=x%y;
x=y;
y=temp;
}
return x;
}
static int lcm(int x,int y) {
temp=gcd(x,y);
return ((x*y)/temp);
}
static int ngcd(int a[]) { //求n个数的最大公约数
int i=0; //下标
temp=gcd(a[i],a[i+1]);//先求出前俩个数的最大公约数,并i+2开始准备与第三个数相比
i=i+2;
while(i<a.length) {
temp=gcd(temp,a[i]);
i++;
}
return temp;
}
static int nlcm(int a[]) { //求n个数的最小公倍数
int i=0;
temp=lcm(a[i],a[i+1]);
i=i+2;
while(i<a.length) {
temp=lcm(temp,a[i]);
i++;
}
return temp;
}
static int hankson(int x,int y,int z,int g) {
int s=y; //表示x
if(y>g)
return 0;
else {
while(s>=y&&s<=g) { //通过思考,会发现x的值会在a1和b1之间,即y与g之间
if(gcd(s,x)==y&&lcm(s,z)==g) {
count++; //统计x的数量
s++;
}
else
s++;
}
}
return count;
}
static int panduan(int x,int y,int z,int g) {
if(x%y!=0||g%z!=0) {
System.out.println("输入的数据不规范!请重新运行程序!");
return 0; //干掉程序重新输入
}
else
return 1;
}
public static void main(String[] args) {
// TODO 自动生成的方法存根
try{
Scanner in=new Scanner(System.in);
int n;
System.out.println("请选择1(求n个数的最大公约数和最小公倍数)或者2(Hankson的问题):");
n=in.nextInt();
switch(n) {
case 1:{
System.out.println("请输入有多少个数:");
n=in.nextInt();
int[] a=new int[n];
for(int i=0;i<a.length;i++)
a[i]=in.nextInt();
System.out.println("最大公约数为:"+ngcd(a));
System.out.println("最小公倍数为:"+nlcm(a));
} break;
case 2:{
System.out.println("请输入有几组数:");
n=in.nextInt();
int[] a=new int[4]; //参数
int[] b=new int[n]; //存放结果
int t=0; //存放结果的下标
for(int j=0;j<n;j++) {
for(int i=0;i<4;i++) {
a[i]=in.nextInt();
}
panduan(a[0],a[1],a[2],a[3]);
hankson(a[0],a[1],a[2],a[3]);
b[t]=count;
t++; //存放结果的下标t++
count=0; //初始化计数器为0,方便进行下一行的计数
}
for(int i:b) //输出结果数组
System.out.println(i);
} break;
default:
System.out.println("没有这个选项,请重新输入!");
}
}catch(Exception e) {
System.out.println("输入的数字不是正整数,请重新输入!");
}
}
}
经验归纳:
一开始,我想用ArrayList集合创建一个动态数组,但是操作复杂!后来发现可以在键盘上输入数组的大小传参给数组。这种方法也可以当做动态数组!
nextInt();这个函数以前也用到过,但是在做这个程序的时候有忘了,有重新温习了一遍!这个函数接受键盘上输入的正整数,忽略空格和换行符,只读数据。
注意循环体的结束条件,一定要有结束条件,否则一直死循环,找错误浪费时间。