题目链接:https://codeforces.com/problemset/problem/431/C
题意:
定义一个 $k$ 树,即所有节点都有 $k$ 个儿子节点,相应的这 $k$ 条边的权重分别为 $1,2, \cdots, k$。
现在要你求出有多少条路径,从根节点出发,满足路径上至少有一条边的权重不小于 $d$,且路径上的边权总和等于 $n$。
题解:
先记 $f[x]$ 表示,对于一棵 $k$ 树,边权和为 $x$ 的路径有多少条。
此时,若将 $k$ 个 $k$ 树的根作为兄弟,将它们都连在一个新的根节点下,发现构成的依然是一棵 $k$ 树,因此容易想到 $k$ 棵子树往根节点转移的状态转移方法。
然而题目还有一个要求,要路径的最小边权不小于 $d$,那么很简单,我们可以扩展一维,
用 $f[x][1]$ 表示存在一条边的边权不小于 $d$ 的状态,而 $f[x][0]$ 则表示不存在。
AC代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1e9+7; int n,k,d; ll f[205][2]; int main() { cin>>n>>k>>d; memset(f,0,sizeof(f)); for(int x=1;x<=k;x++) { if(x<d) f[x][0]=1, f[x][1]=0; else f[x][0]=0, f[x][1]=1; } for(int x=1;x<=n;x++) { for(int w=1;w<=k;w++) { if(x-w<=0) break; if(w<d) { f[x][0]+=f[x-w][0], f[x][0]%=mod; f[x][1]+=f[x-w][1], f[x][1]%=mod; } else { f[x][1]+=f[x-w][0]+f[x-w][1]; f[x][1]%=mod; } } } cout<<f[n][1]<<endl; }