【洛谷】P1025 数的划分 题解
原题地址:https://www.luogu.org/problem/P1025
题目描述
将整数n分成k份,且每份不能为空,任意两个方案不相同(不考虑顺序)。
例如:n=7,k=3,下面三种分法被认为是相同的。
1,1,5;
1,5,1;
5,1,1.
问有多少种不同的分法。
输入输出格式
输入格式:
n,k (6<n≤200,2≤k≤6)
输出格式:
1个整数,即不同的分法。
输入输出样例
输入样例#1:
7 3
输出样例#1:
4
说明
时空限制: 1000ms/128MB
四种分法为:
1,1,5;
1,2,4;
1,3,3;
2,2,3.
思路:
1、把n划分为k个,那么先从n中拿一个x,题目便变为将(n-x)分为m-1种,为了防止不会发生重复的情况,要保证每次拿的x不会比上一次拿的x要小,所以我们可以依次拿一个1出来,递推式为f[i-1][j-1],即有1的情况;
2、没有1的情况,可以看成为j个元素预分配一个1,剩下的便没有1,即f[i-j][j]。故当i>j时便有了递推式f[i][j]=f[i-1][j-1]+f[i-j][j]。
3、要注意当j为1时只有一种,当j为0时则不存在;当i为1或0时则不存在。
代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
int f[205][10];
using namespace std;
int main()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
f[i][1]=1; //将i划分成1份肯定只有一种
f[i][0]=1; //将i划分成0份肯定不存在
}
for(int i=2;i<=k;i++)
{
f[1][i]=0; //将1划分成i份(i>1)肯定不存在
f[0][i]=0; //将0划分成i份(i>1)肯定不存在
}
for(int i=2;i<=n;i++)
{
for(int j=2;j<=k;j++)
{
if(i>j)
f[i][j]=f[i-1][j-1]+f[i-j][j];
else //i<=j的情况
f[i][j]=f[i-1][j-1];
}
}
printf("%d",f[n][k]);
return 0;
}