天天看點

複雜的整數劃分問題-百練4119

将正整數n 表示成一系列正整數之和,n=n1+n2+…+nk, 其中n1>=n2>=…>=nk>=1 ,k>=1 。

正整數n 的這種表示稱為正整數n 的劃分。

Input

标準的輸入包含若幹組測試資料。每組測試資料是一行輸入資料,包括兩個整數N 和 K。 

(0 < N <= 50, 0 < K <= N)

Output

對于每組測試資料,輸出以下三行資料: 

第一行: N劃分成K個正整數之和的劃分數目 

第二行: N劃分成若幹個不同正整數之和的劃分數目 

第三行: N劃分成若幹個奇正整數之和的劃分數目

Sample Input

5 2      

Sample Output

2
3
3      

Hint

第一行: 4+1, 3+2, 

第二行: 5,4+1,3+2 

第三行: 5,1+1+3, 1+1+1+1+1+1

#include <iostream>
#include <string>
#include <string.h>
using namespace std;

int N,K;
int dp1[55][55];//dp1[i][j]是把整數i分成j份
int dp2[55][55];//分成若幹個不相等整數
int g[55][55];//分成若幹偶數
int f[55][55];//分成若幹奇數

void ac1()
{
    memset(dp1,0,sizeof(dp1));
    dp1[0][0]=1;
    for(int i=1;i<=N;i++)
    {
        for(int j=1;j<=i;j++)
        {
            dp1[i][j]=dp1[i-j][j]+dp1[i-1][j-1];
        }
    }
    cout<<dp1[N][K]<<endl;
}

void ac2()
{
    memset(dp2,0,sizeof(dp2));
    for(int i=0;i<=N;i++)dp2[0][i]=1;
    for(int i=1;i<=N;i++)
    {
        for(int j=1;j<=N;j++)
        {
            if(i>=j)
            {
                dp2[i][j]=dp2[i-j][j-1]+dp2[i][j-1];
            }
            else
            {
                dp2[i][j]=dp2[i][i];
            }
        }
    }
    cout<<dp2[N][N]<<endl;
}

void ac3()
{
    memset(g,0,sizeof(g));
    memset(f,0,sizeof(f));
    f[0][0]=1;
    g[0][0]=1;
    for(int i=1;i<=N;i++)
    {
        for(int j=1;j<=i;j++)
        {
            g[i][j]=f[i-j][j];
            f[i][j]=g[i-j][j]+f[i-1][j-1];
        }
    }
    int ans=0;
    for(int i=1;i<=N;i++)ans+=f[N][i];
    cout<<ans<<endl;
}

int main()
{
    while(cin>>N>>K)
    {
        ac1();
        ac2();
        ac3();
    }
    return 0;
}