/*
第一行:将n划分成若干正整数之和的划分数。
状态转移方程:dp[i][j]:和为i、最大数不超过j的拆分数
dp[i][j]可以分为两种情况:1、拆分项至少有一个j 2、拆分项一个j也没有
dp[i][j]=dp[i-j][[j]+dp[i][j-1]
第二行:将n划分成k个正整数之和的划分数。
dp[n-k][k]:相当于把k个1从n中拿出来,然后和n-k的拆分项相加的个数
第三行:将n划分成若干最大不超过k的正整数之和的划分数。
dp[n][k]
第四行:将n划分成若干奇正整数之和的划分数。
dp1[i][j]是当前的划分数为i,最大值为j时的中的划分数,则状态转移方程为
dp1[i][j]=dp1[i][i]if(j>i&&j%2==1)
=dp1[i][i-1]if(j>i&&j%2==0)(最大数不可能为偶数)
=dp1[i-j][j]+dp1[i][j-2]没用到j时划分不变,即dp1[i][j-2],用到则是dp1[i-j][j];
第五行:将n划分成若干完全不同正整数之和的划分数。
dp2[i][j]可以分两种情况:1、dp1[i][j-1]为不选择j时的方案 2、dp1[i-j][j-1]为选择j时的方案
0-1背包:dp2[i][j]=dp2[i][j-1]+dp2[i-j][j-1]
第六行:将n划分成不超过k个正整数之和的划分数。
dp[n][k]: ferrers共轭图像
比如 24=5+5+5+4+3+2,6个数,最大数为5
24=6+6+5+4+3 5个数,最大数为6
*/
#include <stdio.h>
#define N 52
int dp[N][N] = {0} , dp1[N][N] = {0} , dp2[N][N] = {0} ;
void Divid(){
dp[0][0] = 1 ;
for( int i = 0 ; i < N ; i++ )
for( int j = 1 ; j < N ; j++ ){
if( i < j ) //当i<j时 只能j分到i而已,所以情况有1种
dp[i][j] = dp[i][i] ;
else
dp[i][j] = dp[i-j][j] + dp[i][j-1] ;
}
}
void Divid1(){
for( int i = 1 ; i < N ; i++ )
dp1[i][1] = 1 ; //最大值为1时只能有本身组成,Answer为1
for( int i = 1 ; i < N ; i+=2 )
dp1[0][i] = 1 ;
dp1[0][0] = 1 ;
for( int i = 1 ; i < N ; i++ )
for( int j = 3 ; j < N ; j+=2 ){ //j是永远的奇数
if( j > i ){
if( i&1 )
dp1[i][j] = dp1[i][i] ;
else
dp1[i][j] = dp1[i][i-1] ;
}
else
dp1[i][j] = dp1[i-j][j] + dp1[i][j-2] ;
}
}
void Divid2(){
for( int i = 1 ; i < N ; i++ ){
dp2[0][i] = 1 ;
dp2[1][i] = 1 ;
}
for( int i = 2 ;i < N ; i++ )
for( int j = 1 ;j < N ; j++ ){
if( j > i )
dp2[i][j] = dp2[i][i] ;
else
dp2[i][j] = dp2[i-j][j-1] +dp2[i][j-1] ;
}
}
int main(){
int n , k ;
Divid() ;
Divid1() ;
Divid2() ;
while( ~scanf( "%d%d" , &n , &k ) )
{
printf( "%d\n" , dp[n][n] ) ;
printf( "%d\n" , dp[n-k][k] ) ;
printf( "%d\n" , dp[n][k]) ;
printf( "%d\n" , n&1 ? dp1[n][n] : dp1[n][n-1] ) ;
printf( "%d\n\n" , dp2[n][n]) ;
}
return 0;
}