Hankson的“逆问题”

一、题目分析
1.问题:设某未知正整数x满足:
(1)x和a0的最大公约数是a1;
(2)x和b0的最小公倍数是b1。
Hankson的“逆问题”就是求出满足条件的正整数x。
2.分析过程
(1)根据两个要求,得出判断x的条件;
(2)因为x是b1的约数,所以x <= b1,y = b1/x;y也可能符合条件,可以减少循环的次数,确定符合条件数的范围;
(3)每次输入4个数,将这4个数存放到数组中,输入n组数据,即处理n次;
二、程序分析
1.程序组成
1.1 两个类:
(1)Solve类:求出满足要求的x,并输出x的值和x的个数
(2)Improve类:测试类
1.2 三个方法
1.2.1 int Max(int a,int b){}
功能:求两个数的最大公约数

//求两个数的最大公约数(辗转相除法)
    public  static int Max(int a,int b){
        if(a%b == 0){
            return b;
        }else{
            return Max(b,a%b);
        }
    }

1.2.2 void improve(){}
功能:判断符合条件数的个数,并输出

/**
     *
     * @param: []
     * @return: void
     * @Description:判断符合条件数的个数,并输出
     */
    public static void improve(){

        int[] arrays = new int[4];
        int count = 0;
        for(int i = 0;i < 4;i++){
            System.out.print("请输入第"+(i+1)+"个数:");
            int number = new Scanner(System.in).nextInt();
            //将输入的数字存到数组中
            arrays[i] = number;
        }
        //x->(1-sqrt(array[3]))
        for(int x = 1;x*x <= arrays[3];x++){
            if(arrays[3]%x == 0){
                //判断条件:x、arrays[0]的最大公约数是arrays[1];
                //          x和arrays[2]的最小公倍数是arrays[3];
                if(Max(arrays[0],x) == arrays[1]&&((arrays[2]*x)/Max(arrays[2],x)) == arrays[3]){
                    count++;
                    System.out.print(x+" ");
                }
                int y = arrays[3]/x;
                if(x == y){
                    continue;
                }
                if(Max(arrays[0],y) == arrays[1]&&((arrays[2]*y)/Max(arrays[2],y)) == arrays[3]){
                    count++;
                    System.out.print(y+" ");
                }
            }
        }
        System.out.println("满足条件的x有:"+count+"个");
    }

1.2.3 void main(String[] args){}
功能:主方法,测试improve()方法,并输出结果

public static void main(String[] args) {
        int k = 1;
        while(k == 1){
            System.out.println("请输入数据组数:");
            int group = new Scanner(System.in).nextInt();
            //循环输入组数次
            for (int i = 0; i < group; i++) {
                System.out.println("第" + (i + 1) + "组:");
                new Solve().improve();
            }
            System.out.println("继续选择1,退出选择0");
            k = new Scanner(System.in).nextInt();
        }
    }

1.3源程序代码:

package www.program.code;

import java.util.Scanner;

class Solve{
    //求两个数的最大公约数
    public  static int Max(int a,int b){
        if(a%b == 0){
            return b;
        }else{
            return Max(b,a%b);
        }
    }

    /**
     *
     * @param: []
     * @return: void
     * @Description:判断符合条件数的个数,并输出
     */
    public static void improve(){

        int[] arrays = new int[4];
        int count = 0;
        for(int i = 0;i < 4;i++){
            System.out.print("请输入第"+(i+1)+"个数:");
            int number = new Scanner(System.in).nextInt();
            //将输入的数字存到数组中
            arrays[i] = number;
        }
        //x->(1-sqrt(array[3]))
        for(int x = 1;x*x <= arrays[3];x++){
            if(arrays[3]%x == 0){
                //判断条件:x、arrays[0]的最大公约数是arrays[1];
                //          x和arrays[2]的最小公倍数是arrays[3];
                if(Max(arrays[0],x) == arrays[1]&&((arrays[2]*x)/Max(arrays[2],x)) == arrays[3]){
                    count++;
                    System.out.print(x+" ");
                }
                int y = arrays[3]/x;
                if(x == y){
                    continue;
                }
                if(Max(arrays[0],y) == arrays[1]&&((arrays[2]*y)/Max(arrays[2],y)) == arrays[3]){
                    count++;
                    System.out.print(y+" ");
                }
            }
        }
        System.out.println("满足条件的x有:"+count+"个");
    }
}

/**
 * @Author:Star
 * @Date:Created in 13:45 2019/3/21
 * @Description:解决Hankson问题:
 * 设某未知正整数x满足:
 * 1、  x和a0的最大公约数是a1;
 * 2、  x和b0的最小公倍数是b1。
 * Hankson的“逆问题”就是求出满足条件的正整数x
 */
public class Improve {
    public static void main(String[] args) {
        int k = 1;
        while(k == 1){
            System.out.println("请输入数据组数:");
            int group = new Scanner(System.in).nextInt();
            //循环输入组数次
            for (int i = 0; i < group; i++) {
                System.out.println("第" + (i + 1) + "组:");
                new Solve().improve();
            }
            System.out.println("继续选择1,退出选择0");
            k = new Scanner(System.in).nextInt();
        }
    }
}

2.流程图分析
在这里插入图片描述
三、调试
1.输入0有错误产生
在这里插入图片描述
2.对输入数据0进行了处理
在这里插入图片描述
四、测试
1.输入数据非法
在这里插入图片描述
五、运行结果
在这里插入图片描述
六、总结
1.逆向思维的提高题,也可以通过将所求值放到已知方法中去,满足条件,则计数器+1;最后输出计数器的值即可。
2.对于一个问题的逆向化求解过程,以前也没有接触过,所以对于我来说编写出良好的代码有些难度,这次的程序采取了较为简单的代入法求解了问题,也是很好的一次训练机会,但是代码编写的还是很不好,后续会继续思考,希望大家可以找出一些做的不好的地方,互相共勉。

猜你喜欢

转载自blog.csdn.net/weixin_44369212/article/details/88752192