最大约数问题—java版

来源:互联网 发布:html5网页编程软件 编辑:程序博客网 时间:2024/06/10 16:11

  问题描述:正整数x的约数是能整除x的正整数。正整数x的约数个数记为div(x)。例如,10有4个约数:1、2、5、10。设a和b是两个正整数,试计算a和b之间约数个数最多的数x。

    问题分析:

    首先以10、20、30这几个数的约数情况来分析约数的个数。

        10=2*5;10有1、2、5、10共4个约数;

        20=2^2*5;20有1、2、4、5、10、20共6个约数;

        30=2*3*5;30有1、2、3、5、6、10、15、30共8个约数。

 

    在上述三个数中,可以发现,每一个数都可以分解为若干个质数(素数)的乘积,而所有的约数中,除了1以外,其他所有的数都可以看成这些质数的乘积,而1可以看成是相关的质数的幂为0的情况。以10和20为例来说明这个问题:

    10的4个约数中,可以看成如下的情况:

        1=2^0*5^0

        2=2^1*5^0

        5=2^0*5^1

        10=2^1*5^1

    20的6个约数中,可以看成是如下的情况:

        1=2^0*5

        2=2^1*5^0

        4=2^2*5^0

        5=2^0*5^1

        10=2^1*5^1

        20=2^2*5^1

    从这两个例子中可以发现,如果可以确定相关质数的指数,则这个数的约数的个数为相关指数加1后相乘。如10的约数数目为(1+1)*(1+1)=4,20的约数数目为(2+1)*(1+1)=6。

    参考程序如下:

import java.util.ArrayList;

import java.util.List;
import java.util.Scanner;


/**
 * 定义一个类为幂函数类,类中包含两个参数
 * @author LiuYong
 * 算法思路:根据每个数都可以分解为一个或多个质因子相乘的积的形式这一理论,
 * 可以将每个数的因子个数表达为每个质因子出现的次数加1相乘的形式
 * */
class  Monomial { 
int base;//幂函数的底数
int index;//幂函数的指数
//无参构造函数
public Monomial(){

}
//带参构造函数
public Monomial(int base,int index){
this.base=base;
this.index=index;
}
//用于计算输入的数的因子个数,根据以上所表达的算法思路进行
public int Count(List<Monomial> list) {
int count=1;//计算出的因子个数
for(int i=0;i<list.size();i++){//将链表中存放的质因子对象遍历出来
count=count*((list.get(i).index)+1);//根据算法说明对每个质因子指数加一然后求积
}
return count;//返回因子个数
}
}




/**
 * 定义一个整数类,类中包含三个参数,还有一个用于整数分解的方法
 * @author LiuYong
 * 算法思路:每个整数都可以分解为一个或多个质因子的幂函数相乘的形式,
 * 输入一个需要处理的整数,利用for循环,从最小的非一整数开始遍历,
 * 当余数为零时说明为质因子可以保留并将其作为一个对象保存,然后用商
 * 继续除以当前的除数,如果余数不为一则将除数加一,按照上述描述循环
 * 直到除数大于被除数时算法结束
 *  @param conunt代表某一整数同一个质因子出现的次数(被除的次数)
 *  @return 返回一个携有该整数所有质因子对象的链表list
 */
class IntegerWhole{
List<Monomial> list;//定义一个链表来装载所有的质因子对象,但不可以初始化因为一旦初始化,第二个数向链表中添加质因子从已经初始化的链表后边继续插入,而不是从0开始
int temp=2;//除数
Monomial monomial;//未实例化对象
public List<Monomial>  factorization(int number){
list=new ArrayList<Monomial>();
   for(int i=2;i<=number;i++){
    int remainder=0;//初始化余数,只能将他当做这个类的局部变量,如果是全局变量就会产生和list一样的效果
    int count=-1;//初始化整数的同一个质因子出现的次数,值为-1,也可以为零,为零时count要放到if语句里
    while(remainder==0){
    remainder=number%i;//求出余数,如果余数为0代表i为number的质因子,否则不是
    if(remainder==0){//限制条件:只有当余数为零时,即i为质因子,才将number再次除以质因子来得到下一个数来参与质因子的求得
    number/=i;//将商赋值给number,继续向下取质因子
    }
    count++;
    }
    monomial=new Monomial(i,count);//初始化一个幂函数对象,并将底数与指数传进去
    list.add(i-2, monomial);//将初始化的幂函数对象加到链表中
   }

return list;
}
}


/**
 * 作为一个判断类,拥有一个判断方法用于判断给定的正整数中质因子最多的那个,并将其输出
 * @author LiuYong
 * @param a,b  分别初始化出来接收稍小正整数min与稍大正整数max两个数的质因子个数
 * @version 2013-9-1  下午2:32:17
 */
class Judge{
IntegerWhole intwho=new IntegerWhole();
Monomial mon=new Monomial();
//初始化a,b
int a=0;
int b=0;
/**
* 用于判断输入的两个数中质因子最多的个数并将其返回
*  @return  返回一个字符串,既可以是提示语句也可以是质因子最多的个数
*/
public String judgeMax(int min,int max){
if(min<=max){//拦截所有不满足a<b这一题意的参数,并返回一句提示语句
if(min<=0||max<=0){//拦截所有不是正整数的参数,并返回一句提示语句
return "比较的两个数不得有一个为非正整数!";
}else{
a=mon.Count(intwho.factorization(min));//求出较小值的质因子个数
b=mon.Count(intwho.factorization(max));//求出较大值的质因子个数
return a<b?Integer.toString(b):Integer.toString(a);//返回字符串形式质因子个数
}
}else{
return "没有满足‘a<=b’的题意";
}
}


}




/**
* 主干思路:知道质因子出现的次数(需要有一个幂函数类)-->根据质因子的指数计算因子个数(需要一个整数类)-->将两个得到的因子数进行比较得出最大者(需要一个判断类)
* @author LiuYong
* @version 2013-9-1  下午3:29:54
*/
public class Section1_3{
public static void main(String[] args) {
Judge judge=new Judge();
Scanner scan=new Scanner(System.in);
System.out.println("请输入要比较的两个数");
int sca1=scan.nextInt();
int sca2=scan.nextInt();
System.out.println(judge.judgeMax(sca1, sca2));
}
}