题目链接

https://vjudge.net/contest/398864#problem/B

解题思路

规定仅顺序不同的方案为同一个方案。
因此,我们就要限制一下寻找的方法:
找到的这一串数,必须是单调的,如果不是单调寻找必然会存在重复方案。
样例为例,以1开头的:1 1 5,1 2 4,1 3 3,2 2 3不规定单调增的话:1 1 5,1 2 4,1 3 3,1 4 2……不再列举下去了,显然已经出现重复的了。
这也就是说,每个数的列举都是有范围的。
样例,第一位只能列举1,2;当第一位为1时,第二位列举1,2,3,当第一位为2时,第二位列举2;……。
这有什么规律吗?
理解一下,并不是靠找规律,可以发现当前位必须不小于前一位(毋庸置疑,因为递增),且当前位不能超过剩下数的平均值(样例,已经列举了第一位为2,那么剩下的数为7-2=5,此时要求第二位数必须不小于2,且不超过5,所以第二位可以尝试的范围为[2,5];同样的,再确定第二位为2时,第三位的可尝试列举范围为[2,3])
这样一来,我们就可以用dfs解决了。
(真没想到是dfs,以为是数学题,能直接算出答案)

AC代码

#include<bits/stdc++.h>
#define sc(x,y) scanf("%d%d",&x,&y)
#define pr(x) printf("%d",x)
using namespace std;
int n,k,cnt;
void dfs(int pre,int sum,int step){//pre代表前一位列举的数,sum代表当前位之前的和,step代表进行到第几位的列举了
    if(step==k) {cnt++;return ;}
    for(int i=pre;i<=(n-sum)/(k-step+1);i++)
        dfs(i,sum+i,step+1);
}
int main(){
    sc(n,k);
    dfs(1,0,1);//第一位要从1开始尝试列举,且第一位之前的和为0
    pr(cnt);
}