算法设计与分析: 2-14 整数因子分解问题

这篇博客介绍了如何解决整数因子分解问题,详细阐述了问题描述,通过递归和动态规划两种方法进行分析。递归部分提供了Java实现,并展示输入输出示例。动态规划部分同样包含两个Java版本的代码,同样配有输入输出示例。

2-14 整数因子分解问题


问题描述

大于1的正整数n可以分解为:n=x1x2xmn=x1∗x2∗…∗xm。例如,当n=12 时,共有8 种不同的分解式:
12=12;
12=6*2;
12=4*3;
12=3*4;
12=3*2*2;
12=2*6;
12=2*3*2;
12=2*2*3。
对于给定的正整数n,计算n共有多少种不同的分解式。


分析

设h(n)为n的划分数
h(1) = 1
h(2) = 1
h(n)=h(n/2)+h(n/3)+...+h(n/n)h(n)=h(n/2)+h(n/3)+...+h(n/n) (前提是能被整除)


递归

Java

import java.util.Scanner;

public class ZhengShuYinZiFenJie {

    private static int total=0;

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int n;

        while(true){
            //还原初始值
            total = 0;
            n = input.nextInt();

            recursive(n); //递归调用

            System.out.println(total);
            System.out.println("-------------");

        }
    }

    private static void recursive(int n){
        if(n == 1)
            total++;
        else
            for(int i=2; i<=n; i++)
                if(n%i == 0)
                    recursive(n/i);

    }
}

Input & Output

12
8
-------------
12
8
-------------
3
1
-------------
4
2
-------------
5
1
-------------
1
1
-------------
56
20
-------------
56
20
-------------
66
13
-------------
67
1
-------------

动态规划

Java: version 1

import java.util.Scanner;

public class ZhengShuYinZiFenJie1 {

    private static int total=0;
    private static int[] h = new int[10000];

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int n;

        while(true){
            //还原初始值
            total = 0;
            h = new int[10000];
            n = input.nextInt();

            total = dynamic(n);

            System.out.println(total);
            System.out.println("---------------");

        }
    }

    //动态规划
    private static int dynamic(int n){
        h[1] = 1;
        h[2] = 1;
        for(int i=3; i<=n; i++)
            for(int j=2; j<=i; j++)
                if(i%j == 0) //如果j能被i整除
                    h[i] += h[i/j];
        return  h[n];
    }

}

Input & Output

12
8
---------------
12
8
---------------
3
1
---------------
4
2
---------------
1
1
---------------
56
20
---------------

Java: version 2

import java.util.Arrays;
import java.util.Scanner;

public class ZhengShuYinZiFenJie2 {

    private static int[] divisors; //保存n的因子,k为a数组最后一位因子的下一位所值的地方(下标)
    private static int[] h; //保存结果
    private static int n;
    private static int k; //k为divisors数组最后一位元素的下一位(下标)
    private static int total;

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);

        while (true){
            k = 0;
            h = new int[1005];
            divisors = new int[1005];

            n = input.nextInt();

            divisor(n);

            Arrays.sort(divisors, 0, k);

            total = dynamic();

            System.out.println(total);
            System.out.println("---------------");
        }
    }

    private static int dynamic(){
        h[0]=1; //初始
        for(int i=1; i<k; i++){
            for(int j=0; j<i; j++){
                if(divisors[i]%divisors[j] == 0){
                    h[i] += h[j];
                }
            }
        }
        return h[k-1];
    }

    private static void divisor(int n){
        int i;
        for(i=1; i<Math.sqrt(n); i++){
            if(n%i == 0){
                divisors[k++] = i;
                divisors[k++] = n/i;
            }
        }
        if(i*i == n) //处理因子相同,且只可能出现在i*i==n(即i=sqrt(n))处
            divisors[k++] = i;
    }
}

Input & Output

12
8
---------------
12
8
---------------
3
1
---------------
4
2
---------------
66
13
---------------

Reference

王晓东《计算机算法设计与分析》(第3版)P47

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值