描述
将正整数n 表示成一系列正整数之和,n=n1+n2+…+nk, 其中n1>=n2>=…>=nk>=1 ,k>=1 。
正整数n 的这种表示称为正整数n 的划分。
输入
标准的输入包含若干组测试数据。每组测试数据是一行输入数据,包括两个整数N 和 K。
(0 < N <= 50, 0 < K <= N)
输出
对于每组测试数据,输出以下三行数据:
第一行: N划分成K个正整数之和的划分数目
第二行: N划分成若干个不同正整数之和的划分数目
第三行: N划分成若干个奇正整数之和的划分数目
样例输入
5 2
样例输出
2
3
3
提示
第一行: 4+1, 3+2,
第二行: 5,4+1,3+2
第三行: 5,1+1+3, 1+1+1+1+1+1
解题思路
- N划分成K个正整数之和的划分数目
dp[i][j] 代表整数 i 拆成 j 个正整数有多少种拆法,那么 dp[i][j] = dp[i-j][j] + dp[i-1][j-1] 分成两种情况- 拆分后的正整数中没有1 那么就等价于 dp[i-j][j] 相当于 每个数都已经分配了 1 然后剩余 i - j 再来拆成 j 个正整数
- 拆分后的正整数中至少有一个1 dp[i-1][j-1]
边界条件 dp[i][1]=1 dp[i][i]=1
- N划分成若干个不同正整数之和的划分数目
dp[i][j] 表示从前 i 个数中挑选若干数凑成 j 的选法,那么 dp[i][j] = dp[i-1][j-i] + dp[i-1][j]- dp[i-1][j-i] 选第 i 个数 再从前面 i - 1 个数中选若干个凑出 j - i
- dp[i-1][j] 不选第 i 个数 从前面 i - 1 个数中选出若干个凑出 j
- N划分成若干个奇正整数之和的划分数目
dp[i][j] 代表整数 i 拆成 j 个奇正整数有多少种拆法,那么 dp[i][j] = dp[i-2*j][j] + dp[i-1][j-1]- 同第一种情况 拆分后的正整数中没有1 那么就等价于 dp[i-2*j][j] 相当于 每个数已经分配了2 然后剩余 i - 2*j 再来拆成 j 个正奇数
- 拆分后的正奇数中至少有一个1 dp[i-1][j-1]
边界条件 如果 i 是奇数 那么 dp[i][1] = 1 如果 i == j 那么 dp[i][j] = 1;
AC Code
#include<iostream>
#include<cmath>
#include<stack>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const double PI=acos(-1);
const double EPS=1e-6;
const int MAXN=100+10;
int n,k;
int dp1[MAXN][MAXN];//dp1[i][j]表示将整数i拆成j个正整数的拆法
int dp2[MAXN];//dp2[j]凑成j的不同选法 (滚动数组)
int dp3[MAXN][MAXN];//dp3[i][j]表示将整数i拆成j个奇正整数的拆法
int solution1(){
memset(dp1,0,sizeof(dp1));
for(int i=1; i<=n; ++i){
dp1[i][1]=1;
for(int j=1; j<=k; ++j){
if(i==j) dp1[i][j]=1;
else if (i>=j) dp1[i][j]=dp1[i-j][j]+dp1[i-1][j-1];//不包含1的情况和包含1的情况
}
}
return dp1[n][k];
}
int solution2(){
memset(dp2,0,sizeof(dp2));
for(int i=1; i<=n; ++i){
for(int j=n; j>=0; --j){
if(j==1||j==0) dp2[j]=1;
else if (j>=i) dp2[j]=dp2[j-i]+dp2[j];//选i和不选i的情况
// printf("dp[%d]=%d ",j,dp2[j]);
}
// printf("\n");
}
return dp2[n];
}
int solution3(){
memset(dp3,0,sizeof(dp3));
for(int i=1; i<=n; ++i){
if(i%2) dp3[i][1]=1;
for(int j=1; j<=n; ++j){
if(i==j) dp3[i][j]=1;
else if (i>=2*j) dp3[i][j]=dp3[i-2*j][j]+dp3[i-1][j-1];
else dp3[i][j]=dp3[i-1][j-1];
}
}
int cnt=0;
for(int i=1; i<=n; ++i)
cnt+=dp3[n][i];
return cnt;
}
int main(){
freopen("C:\\Users\\Ambition\\Desktop\\in.txt","r",stdin);
freopen("C:\\Users\\Ambition\\Desktop\\out.txt","w",stdout);
while(~scanf("%d%d",&n,&k)){
printf("%d\n%d\n%d\n",solution1(),solution2(),solution3());
}
return 0;
}