Divide integers (recursively) and output the result of the division
Explain the problem, what is integer division?
- n=m1+m2+...+mi; (where mi is a positive integer and 1 <= mi <= n), then {m1,m2,...,mi} is a division of n.
- If the maximum value in {m1,m2,...,mi} does not exceed m, that is, max(m1,m2,...,mi)<=m, it is said to belong to an m partition of n. Here we record the number of m divisions of n as f(n,m);
- For example, when n=5, we can obtain the following divisions (note that m>=5 in the example)
5 = 5
= 4 + 1
= 3 + 2
= 3 + 1 + 1
= 2 + 2 + 1
= 2 + 1 + 1 + 1
= 1 + 1 + 1 + 1 + 1
According to the relationship between n and m, consider the following situations:
(1) When n=1, no matter what the value of m is (m>0), there is only one division, namely {1};
(2) When m=1, no matter what the value of n is, there is only one division, that is, n 1s, {1,1,1,...,1};
(3) When n=m, according to whether n is included in the division, it can be divided into two cases:
(a) In the case where n is included in the division, there is only one, namely {n};
(b) In the case where n is not included in the division, the largest number in the division must also be smaller than n, that is, all (n-1) divisions of n. So q(n,n) =1 + q(n,n-1);
(4) When n<m, since it is impossible to have negative numbers in the division, it is equivalent to q(n,n);
(5) But when n>m, according to whether the maximum value m is included in the division, it can be divided into two cases:
(a) The case where m is included in the division, ie {m, {x1,x2,...xi}}, where the sum of {x1,x2,...xi} is nm, so in this case it is q(nm ,m)
(b) In the case where m is not included in the division, all the values in the division are smaller than m, that is, the (m-1) division of n, the number of which is q(n, m-1);
So q(n, m) = q(nm, m)+q(n,m-1);
In summary:
q(n, m) = 1; (n=1 or m=1)
q(n,m) = q(n, n); (n<m)
1+ q(n, m-1); (n=m)
q(n-m,m)+q(n,m-1); (n>m)
Recursive algorithm:
code show as below:
#include<iostream> using namespace std; int q(int n, int m) { if(n < 1 || m < 1) return 0; if(n == 1 || m == 1) return 1; if(n < m) return (n, n); if(n == m) return q(n, m-1) + 1; return q(n, m-1) + q(n-m, m); } int main() { cout<<q(6, 6)<<endl; return 0; }
Dynamic programming:
#include <iostream> #define MYDATA long long const MYDATA MOD = 1000000007; #define MAXNUM 1005 //Maximum times long ww[MAXNUM * 11][MAXNUM * 11]; long dp(int n, int max); using namespace std; int main() { int n; int m; long count; while (1) { cin >> n; cout << dp(n, n) << endl; } return 0; } long dp(int n, int max) { for (int i = 1; i <= n; i++) for (int j = 1; j <= i; j++) { if (j == 1 || i == 1) { ww[i][j] = 1; } else { if (j == i) ww[i][j] = (ww[i][j - 1] + 1) % MOD; else if ((i - j) < j) ww[i][j] = (ww[i - j][i - j] + ww[i][j - 1]) % MOD; else ww[i][j] = (ww[i - j][j] + ww[i][j - 1]) % MOD; } } return ww[n][max]; }
Output result:
#include <stdio.h> int mark[256]; int n; void DFS(int sum, int k, int prio) { if(sum > n) { return; } else if(sum == n) { int i; printf("="); for( i = 0; i < k-1; i++) { printf("%d+",mark[i]); } printf("%d\n",mark[i]); } else { for(int j = prio; j > 0; j--) { mark[k] = j; sum += j; DFS(sum,k+1,j); sum -= j; // restore the scene } } } int main() { scanf("%d", &n); DFS(0, 0, n); return 0; }