数的划分
题目描述
将整数 n 分成 k 份,且每份不能为空,问有多少种不同的分法。当 n=7,k=3 时,下面三种分法被认为是相同的:1,1,5 ; 1,5,1 ; 5,1,1
输入格式
一行两个数 n , k。
输出格式
一行一个整数,即不同的分法数。
样例输入
7 3
样例输出
4
样例解释
四种分法为:1,1,5 ;1,2,4 ;1,3,3 ;2,2,3
数据范围与提示
6<=n<=200
2<=k<=6
大致思路
- 由于重复的的组合只算一次,所以我们按升序分解,所以当前节点不应小于前一个节点(可等于)即 a [ i − 1 ] < = a [ i ] a[i-1]<=a[i] a[i−1]<=a[i].
- 数字n,分k份,若当前是分第K份,则还需要分 ( K − k + 1 ) (K-k+1) (K−k+1)次, a[i]之前的数的和为 S U M = ∑ j = 1 j < i − 1 a [ j ] SUM=\sum_{j=1}^{j<i-1} a[j] SUM=∑j=1j<i−1a[j] ,还需分 ( n − S U M ) (n-SUM) (n−SUM)因此a[i]的最大值为 n − S U M K − k + 1 n-SUM\over K-k+1 K−k+1n−SUM
-
dfs部分
void dfs(int cnt){
if(cnt>k)return;
if(cnt==k){
if(n>=a[k-1]){
ans++;
}
return;
}
for(int i=a[cnt-1];i<=n/(k-cnt+1);i++){
a[cnt]=i;
n-=i;
dfs(cnt+1);
n+=i;
}
}
AC NODE
#include<bits/stdc++.h>
using namespace std;
int n,k,a[99999],ans=0;
void dfs(int cnt){
if(cnt>k)return;
if(cnt==k){
if(n>=a[k-1]){
ans++;
}
return;
}
for(int i=a[cnt-1];i<=n/(k-cnt+1);i++){
a[cnt]=i;
n-=i;
dfs(cnt+1);
// for(int j=0;j<=k;j++){
// cout<<a[j]<<" ";
// }
// cout<<endl;
n+=i;
}
}
int main(){
cin>>n>>k;
a[0]=1;
a[1]=1;
dfs(1);
cout<<ans;
return 0;
}