将正整数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
第一行: N划分成K个正整数之和的划分数目:解法
设把i划分为j个的时候的种数为dp[i][j],
分情况讨论:
若j个数中不包含1,则种数为dp[i-j][j]
若j个数中包含1,则种数为dp[i-1][j-1]
因此有dp[i][j]=dp[i-j][j]+dp[i-1][j-1]
第二行: N划分成若干个不同正整数之和的划分数目
设把i划分为j个不同正整数的时候的种数为dp[i][j],
分情况讨论:
若j个数中不包含1,则种数为dp[i-j][j],
若j个数中包含1,则种数为dp[i-j][j-1](因为你得保证另外j-1个盒子里没有1,那么算上即将进去的这个1一同扣除,就是i-j个1。
第三行: N划分成若干个奇正整数之和的划分数目
设把i划分为j个奇数的种数为dp[i][j]
设把i划分为j个非0偶数的种数为op[i][j]
dp[i][j]=op[i-j][j]+dp[i-1][j-1];(若无1,则每个奇数必大于3,那么等价于op[i-j][j],若有1则dp[i-1][j-1]
op[i][j]=dp[i-j][j];(由于偶数必大于等于2,因此全部盒子减1就是奇数的)
AC代码:
#include <iostream>
#include <algorithm>
#include <string>
#include<stdio.h>
#include<set>
#include<queue>
#include<map>
#include<string.h>
#include<vector>
#define FOR(i, a, b) for (int i=a;i<b;++i)
#define FOR_E(i, a, b) for (int i=a;i<=b;++i)
#define CPY(A, B) memcpy(A, B, sizeof(A))
#define CLR(A) memset(A, 0, sizeof(A))
#define CLMAX(A) memset(A,127,sizeof(A))
template<typename T> T MAX(T A,T B){return A > B ? A:B;}
template<typename T> T MIN(T A,T B){return A < B ? A:B;}
template<typename T> T ABS(T A){return A<0? -A:A;}
template<typename T> T gcd(T a,T b){return b==0 ? a:gcd(b,a%b); }
#define INF 0x3f3f3f3f
#define LNF 0x3f3f3f3f3f3f3f3f
typedef long long ll;
typedef double db;
const int di[]={0,-1,0,1};
const int dj[]={-1,0,1,0};
const double eps = 1e-9;
using namespace std;
ll dp[55][55];
ll op[55][55];
int main(){
int n,k;
while(cin>>n>>k){
CLR(dp);
CLR(op);
dp[1][1]=1;
dp[1][0]=0;
FOR(i,2,n+1){
dp[i][1]=1;
dp[i][i]=1;
FOR(j,2,i){
dp[i][j]=dp[i-j][j]+dp[i-1][j-1];
}
}
cout<<dp[n][k]<<endl;
CLR(dp);
dp[1][1]=1;
dp[1][0]=0;
FOR(i,2,n+1){
dp[i][1]=1;
dp[i][i]=0;
FOR(j,2,i){
dp[i][j]=dp[i-j][j-1]+dp[i-j][j];
}
}
ll ans=0;
FOR(i,1,n+1){
ans+=dp[n][i];
}
cout<<ans<<endl;
CLR(dp);
FOR(i,1,55){
if(i%2==0){
dp[i][1]=0;
op[i][1]=1;
}
else {
dp[i][1]=1;
op[i][1]=0;
}
}
FOR(i,2,n+1){
if(i%2==0){
op[i][1]=1;
dp[i][1]=0;
}
else{
op[i][1]=0;
dp[i][1]=1;
}
dp[i][i]=1;
op[i][i]=0;
FOR(j,2,i){
dp[i][j]=op[i-j][j]+dp[i-1][j-1];
op[i][j]=dp[i-j][j];
}
}
ans=0;
FOR(i,1,n+1){
ans+=dp[n][i];
}
cout<<ans<<endl;
}
}