Two solutions to integer division problem

Problem Description

Given an integer num , how many different ways can it be divided into the sum of one or more integers.

For example:
num=5
All division methods are as follows:
* 5=5
* 1+4=5
* 2+3=5
* 1+1+3=5
* 1+2+2=5
* 1+1+1 +2=5
* 1+1+1+1+1=5
(note that 1+1+3=5 and 1+3+1=5 are regarded as a division method)


divide and conquer

Divide and conquer ideas

Given an integer num , the problem can be divided into several subproblems. For example, if num=5, we can first find the division method of dividing 5 into 1 number, and then find the division method of dividing 5 into 2 numbers. Finally, we can find the division method of dividing 5 into 5 numbers. Finally, adding the solutions of these sub-problems can get the answer we want.

And these sub-problems are of the same kind. The description of generalization is that given an integer num , how many division methods are there to divide it into the sum of k integers .

For this problem, we can divide it into several sub-problems.

To divide num into k integers, we first take an integer t , such that t < num , this t is the first integer we divide from num , and in the case of ensuring that the division is not repeated (how to ensure that it is not repeated in the code) Explain in detail) how many different t can be found , the solution of the original problem should be added. Then the original problem becomes the problem of how many ways to divide num-t into k-1 integers.

In this way, the solution of the problem can be obtained.


Code parsing

#pragma comment(linker, "/STACK:102400000,102400000")  
#include <iostream>  
#include <cstring>  
#include <cstdlib>  
#include <cstdio>   
#include <algorithm>  
#include <cmath>  
#include <stack>  
#include <string.h>  

using namespace std;
const int MAXN = 55;
int num;
stack<int> temp;
//列用栈的性质保证划分序列非递减

int solve(int num, int k) {
    //返回将num分为k个数的非递减序列的分法总数
    if (k == 1) return 1;
    int ans = 0;
    for (int i = 1; i <= num/k; i++) {
        //保证划分得到的整数序列非递减
        //则左边的数不大于右边的数
        //i最大不能大于num/k 
        //否则非递减不能得到保证
        if (i < temp.top()) continue;
        //temp栈顶保存当前划分序列最右边(及最大)整数
        //若新加入i不能保证非递减则跳过
        temp.push(i);
        ans += solve(num - i, k - 1);
        temp.pop();
    }
    return ans;
}

int main(){
    temp.push(0);
    while (scanf("%d", &num) != EOF) {
        int ans = 0;
        for (int i = 1; i <= num; i++)
            ans += solve(num, i);
        printf("%d\n", ans);
    }
    return 0;
}

dynamic programming

Dynamic rules

After reading the idea of ​​divide and conquer, the difficulty of the problem is obvious, that is, given an integer num , how many division methods are there to divide it into the sum of k integers .

  1. If num is divided into k integers, and there is 1 in these k integers , then divide this 1 , and the solution of the problem is the solution of dividing the integer num-1 into k-1 integers.
  2. If num is divided into k integers, and there is no 1 in the k integers, then after each of the k integers is decremented by 1, there are still k integers , and at this time , the division method composed of the k integers is the problem: The integer num-k divides the solution into k integers.

Using the bottom-up motion gauging strategy, the solution of the original problem is obvious after the solutions of 1. and 2. are known.

The state transition equation is as follows:

dp[i][j] = dp[i - j][j] + dp[i - 1][j - 1];

Code parsing

#pragma comment(linker, "/STACK:102400000,102400000")  
#include <iostream>  
#include <cstring>  
#include <cstdlib>  
#include <cstdio>   
#include <algorithm>  
#include <cmath>  
#include <stack>  
#include <string.h>  

const int MAXN = 1001;
int dp[MAXN][MAXN];
//dp[num][k] 表示将num分为k个数的划分方法数量

void dfs() {
    for (int i = 1; i < MAXN; i++) {
        for (int j = 2; j < i; j++) {
            dp[i][j] = dp[i - j][j] + dp[i - 1][j - 1];
        }
    }
}

int main(){
    int num, k;
    memset(dp, 0, MAXN*MAXN * sizeof(int));

    //初始化
    for (int i = 1; i < MAXN; i++)
        dp[i][1] = 1;
    //将每个数划分为一个数(本身)只有一种方法

    dfs();

    scanf("%d%d", &num, &k);
    printf("%d", dp[num][k]);
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325530675&siteId=291194637