Quite recently a creative student Lesha had a lecture on trees. After the lecture Lesha was inspired and came up with the tree of his own which he called a k-tree.
A k-tree is an infinite rooted tree where:
- each vertex has exactly k children;
- each edge has some weight;
- if we look at the edges that goes from some vertex to its children (exactly k edges), then their weights will equal 1, 2, 3, ..., k.
The picture below shows a part of a 3-tree.
Help Dima find an answer to his question. As the number of ways can be rather large, print it modulo1000000007 (109 + 7).
A single line contains three space-separated integers: n, k and d (1 ≤ n, k ≤ 100; 1 ≤ d ≤ k).
Print a single integer — the answer to the problem modulo 1000000007 (109 + 7).
3 3 2
3
3 3 3
1
4 3 2
6
4 5 2
7
题意:
k-Tree,每个节点有k个儿子,边权分别是1、2、……、K。
现求出从根节点出发,有多少条路径,使得总权值恰好为N,并且每条路径上至少有一条权值不少于d的边。
分析:
dp[i][x]表示当到达i状态时的总数,x为0或1,0表示之前没有使用过>=d的边,1表示之前有使用过>d的边。
则有状态转移方程:
dp[i][0] += dp[i-j][0] , (j < d)
dp[i][1] += dp[i-j][0] , (j>=d)
dp[i][1] += dp[i-j][1]
初始化dp[0][0] = 1;
这题还需要注意数据的类型,不能写成INT,应该写成LONG LONG。。。。。。。。。。这会导致WA。(注意)
#include<iostream> #include<cstdio> #include<cstring> long long dp[200][2]; using namespace std; long long mod = 1000000007; int main() { long long n,k,d; while(~scanf("%I64d%I64d%I64d",&n,&k,&d)) { memset(dp,0,sizeof(dp)); dp[0][0] = 1; for(int i=1;i<=n;i++) { for(int j=1;j<=k;j++) { if(j<d&&i-j>=0) { dp[i][0] += dp[i-j][0]; dp[i][1] += dp[i-j][1]; } else if(j>=d&&i-j>=0) { dp[i][1] += dp[i-j][0]; dp[i][1] += dp[i-j][1]; } dp[i][0] = dp[i][0]%mod; dp[i][1] = dp[i][1]%mod; } } cout<<dp[n][1]<<endl; } return 0; }