题目:
https://www.luogu.org/problem/show?pid=1025
递归:
代码很清楚了;
注意:
为保证划分的唯一性,我们从小到大枚举数字;
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int ans=0;
void dfs(int n,int k,int x)
{
if(k==1) ans++;
else
{
for(int i=x;i<=n/k;i++)
dfs(n-i,k-1,i);
}
return;
}
void solve()
{
int n,k;
scanf("%d%d",&n,&k);
dfs(n,k,1);
cout<<ans<<endl;
}
int main()
{
solve();
return 0;
}
递推:
dp[i][j] : 将数i划分为j个部分的方案数;
转移:dp[i][j]=dp[i-1][j-1]+dp[i-j][j];
因为题目要求划分非0;
所以i的j划分=至少一个划分为1方案数+没有划分为1的方案数;
可以理解为:
1. 取出1份放1 (保证至少有一个划分为1), 此时等同于i-1的j-1划分;
2. 将i-j划分为j份,再把每份+1(保证每个划分一定不为1);
边界:
将i划分为1份的方案数为1;
将i划分为i份的方案数为1(保证每份非0);
输出:
dp[n][k];
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=2001;
int dp[MAXN][MAXN];
int n,k;
void solve()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) dp[i][1]=1,dp[i][i]=1;
for(int i=2;i<=n;i++)
for(int j=2;j<i;j++)
dp[i][j]+=dp[i-1][j-1]+dp[i-j][j];
cout<<dp[n][k];
}
int main()
{
solve();
return 0;
}