整数划分(三)
时间限制:
1000 ms | 内存限制:
65535 KB
难度:
5
-
描述
-
整数划分是一个经典的问题。请写一个程序,完成以下要求。
-
输入
- 每组输入是两个整数n和k。(1 <= n <= 50, 1 <= k <= n) 输出
-
对于输入的 n,k;
第一行: 将n划分成若干正整数之和的划分数。
第二行: 将n划分成k个正整数之和的划分数。
第三行: 将n划分成最大数不超过k的划分数。
第四行: 将n划分成若干个 奇正整数之和的划分数。
第五行: 将n划分成若干不同整数之和的划分数。
第六行: 打印一个空行
样例输入
-
5 2
样例输出
-
7 2 3 3 3
提示
-
样例输出提示:
1.将5划分成若干正整数之和的划分为: 5, 4+1, 3+2, 3+1+1, 2+2+1, 2+1+1+1, 1+1+1+1+1
2.将5划分成2个正整数之和的划分为: 3+2, 4+1
3.将5划分成最大数不超过2的划分为: 1+1+1+1+1, 1+1+1+2, 1+2+2
4.将5划分成若干 奇正整数之和的划分为: 5, 1+1+3, 1+1+1+1+1
5.将5划分成若干不同整数之和的划分为: 5, 1+4, 2+3
#include <stdio.h> #include <string.h> long long d[55][55]; long long res[5]; int s = 0; int n, k, i, j; int main(void){ while(scanf("%d %d", &n, &k) != EOF) { s = 0; memset(d, 0, sizeof(d)); //d(i, j)表示把i分成几个数的和,其中最大数不超过j for(i = 0; i <= n; ++i) { d[i][i] = 1; d[i][0] = 1; d[i][1] = 1; } for(i = 2; i <= n; ++i) { for(j = 2; j < i; ++j) { d[i][j] = d[i - 1][j - 1] + d[i - j][j]; } } int sum = 0; for(i = 1; i <= n; ++i) { sum += d[n][i]; } res[s++] = sum; res[s++] = d[n][k]; memset(d, 0, sizeof(d)); for(i = 1; i <= n; ++i) { for(j = 1; j <= n; ++j) { if(i == 1 || j == 1) d[i][j] = 1; else if(i == j) d[i][j] = 1 + d[i][j - 1]; else if(i < j) d[i][j] = d[i][i]; else d[i][j] = d[i][j - 1] + d[i - j][j]; } } res[s++] = d[n][k]; memset(d, 0, sizeof(d)); for(i = 0; i <= n; ++i) { d[i][1] = 1; if(i & 1) { d[0][i] = 1; } else { d[0][i] = 0; } } d[0][0] = 0; // 将n划分成若干奇正整数之和的划分数。 // dp[i][j]是当前的划分数为i,最大值为j时的中的划分数,则状态转移方程为 // dp[i][j] = dp[i][i] if( j>i && j%2 == 1) // = dp[i][i-1] if( j>i && j%2 == 0)(最大数不可能为偶数) // = dp[i-j][j] + dp[i][j-2] 没用到j时划分不变,即dp[i][j-2],用到则是dp[i-j][j]; for(i = 1; i <= n; ++i) { for(j = 3; j <= n; j += 2) { if(j > i) { if(i & 1) { d[i][j] = d[i][i]; } else { d[i][j] = d[i][i - 1]; } } else { d[i][j] = d[i - j][j] + d[i][j - 2]; } } } if(n & 1) res[s++] = d[n][n]; else res[s++] = d[n][n - 1]; memset(d, 0, sizeof(d)); for(i = 0; i <= n; ++i) { d[i][0] = d[i][1] = 1; } for(i = 2; i <= n; ++i)//0/1背包的变形,有n件物品大小为1,2......n.求将大小为n的背包装满共有几种方案数。 { //那么就有状态转移方程: dp[i][j] = dp[i-1][j] + dp[i-1][j-i]; (j >= i) // dp[i][j] = dp[i-1][j] (j < i) for(j = 2; j <= n; ++j) { if(j < i) d[i][j] = d[i - 1][j]; else d[i][j] = d[i - 1][j] + d[i - 1][j - i]; } } res[s++] = d[n][n]; for(i = 0; i < s; ++i) { printf("%lld\n", res[i]); } printf("\n"); } return 0; }