1. 程式人生 > >NYOJ 571 —— 各種劃分數

NYOJ 571 —— 各種劃分數

時間限制:1000 ms  |  記憶體限制:65535 KB
描述

整數劃分是一個經典的問題。請寫一個程式,完成以下要求。

輸入
每組輸入是兩個整數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 <cstdio>
#include <iostream>
#include <cstring>
#include <string>
using namespace std;

int dp[55][55];

int main ()
{
    int n, k, a, b, c, d, e;
    while(scanf("%d%d", &n, &k) != EOF) {
        // 把正整數i劃分為不超過j的正整數的劃分個數
        for(int i=1; i<=n; i++) {
            
for(int j=1; j<=n; j++) { if(j>i) dp[i][j] = dp[i][i]; else if(j == i) dp[i][j] = dp[i][j-1] + 1; else dp[i][j] = dp[i][j-1] + dp[i-j][j]; } } a = dp[n][n]; c = dp[n][k]; // 把正整數劃分為k個正整數的劃分個數
for(int i=1; i<=n; i++) { for(int j=1; j<=k; j++) { if(j>i) dp[i][j] = 0; else if(j==i) dp[i][j] = 1; else dp[i][j] = dp[i-1][j-1] + dp[i-j][j]; } } b = dp[n][k]; // 把i劃分為不超過j的奇數的劃分個數 int odd = n&1 ? n : n-1; for(int i=1; i<=n; i++) { dp[i][1] = 1; for(int j=3; j<=odd; j+=2) { if(j>i) { if(i&1) dp[i][j] = dp[i][i]; else dp[i][j] = dp[i][i-1]; } else if(j==i) dp[i][j] = dp[i][i-2] + 1; else dp[i][j] = dp[i][j-2] + dp[i-j][j]; } } d = dp[n][odd]; // 把i劃分為不同正整數的劃分個數 for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) { if(j>i) dp[i][j] = dp[i][i]; else if(j == i) dp[i][j] = dp[i][i-1] + 1; else dp[i][j] = dp[i][j-1] + dp[i-j][j-1]; } } e = dp[n][n]; printf("%d\n%d\n%d\n%d\n%d\n\n", a, b, c, d, e); memset(dp, 0, sizeof(dp)); } return 0; }