描述
将正整数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
问题1
N划分成K个正整数之和的划分数目
f[i][j]将i划分为j个正整数的划分数目
如果i=j,只能全部划分为1,只有1种
如果i<j,无法划分
如果i>j,可以分为有1和没有1。有1的话,拿出去一个1,需要划分的数i减1,划分的份数也要减1,也就是f[i-1][j-1];如果没有1,也就是说划分出来的每一份都比1大,那么就将每一份都减去1,i就变成了i-j,划分的份数j不变,即f[i-j][j]
转移方程 f[i][j]=f[i-j][j]+f[i-1][j-1]
void work1()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=i&&j<=k;j++)
{
if(i>j)
f[i][j]=f[i-j][j]+f[i-1][j-1];
if(i==j)
f[i][j]=1;
}
cout<<f[n][k]<<endl;
}
问题2
N划分成若干个不同正整数之和的划分数目
可以先看看分成若干个可以相同的正整数划分数目
f[i][j]表示将i分成若干个不同且不大于j的正整数的划分数目
可以分为有j这个是和没有
有的话,那么剩下需要分的数就为i-j,由于不能有相同的数,那么就不能是不大于j了,需要变成不大于j-1,即f[i-j][j-1]
没有的话,那么就需要将i-1划分为j个数,即f[i-1][j]
转移方程 f[i][j]=f[i][j-1]+f[i-j][j-1]
void work2()
{
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++)
{
f[0][i]=1;
f[i][1]=0;
}
f[1][1]=1;
for(int i=1;i<=n;i++)
for(int j=2;j<=n;j++)
{
if(j<=i)
f[i][j]=f[i][j-1]+f[i-j][j-1];
else
f[i][j]=f[i][i];
}
cout<<f[n][n]<<endl;
}
问题3
N划分成若干个奇正整数之和的划分数目
f[i][j]表示为将i分为j个奇数的划分数目 g[i][j]表示为将i分为j个偶数的划分数目
可以分为有1和无1两种情况
有1,那么需要分的数需要减1,份数减1,即f[i-1][j-1]
无1,那么就将没一份都减1,分的数就为i-j,份数仍j,每一份都减了1.奇数减1变为偶数,所求就变成了将i-j分为j个偶数,即g[i-j][j]
转移方程 f[i][j]=g[i-j][j]+f[i-1][j-1]
void work3()
{
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 s=0;
for(int i=1;i<=n;i++)
s+=f[n][i];
cout<<s<<endl;
}
代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int f[51][51],g[51][51];
int n,k;
void work1()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=i&&j<=k;j++)
{
if(i>j)
f[i][j]=f[i-j][j]+f[i-1][j-1];
if(i==j)
f[i][j]=1;
}
cout<<f[n][k]<<endl;
}
void work2()
{
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++)
{
f[0][i]=1;
f[i][1]=0;
}
f[1][1]=1;
for(int i=1;i<=n;i++)
for(int j=2;j<=n;j++)
{
if(j<=i)
f[i][j]=f[i][j-1]+f[i-j][j-1];
else
f[i][j]=f[i][i];
}
cout<<f[n][n]<<endl;
}
void work3()
{
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 s=0;
for(int i=1;i<=n;i++)
s+=f[n][i];
cout<<s<<endl;
}
int main()
{
while(cin>>n>>k)
{
work1();
work2();
work3();
}
return 0;
}