问题链接是:http://codeforces.com/problemset/problem/431/C
最近,一位有创造力的学生Lesha在树上做了一个讲座。后 讲座Lesha受到启发并想出了他自己的树 他称之为k树。
k-tree是一个无限的有根树,其中:
- 每个顶点都有k个孩子;
- 每条边都有一些重量;
- 如果我们看一下从某个顶点到其子节点的边缘(确切地说 k个边缘),然后它们的权重将等于1,2,3,...,k。
下图显示了3棵树的一部分。
一旦Lesha的好朋友Dima发现了这棵树,他就会 马上想知道:“总重量的路径数n(总和) 从那里开始,路径中边缘的所有权重都在那里 k树的根,并且还包含至少一个重量边缘 至少d?“。帮助Dima找到他的问题的答案。作为数量 方式可以相当大,打印模数1000000007(10 ^ 9 + 7)。 (打开 上面提到的树的图片的问题链接)
输入
单行包含三个以空格分隔的整数:n,k和 d(1≤n,k≤100;1≤d≤k)。输出
打印一个整数 - 问题模的答案 1000000007(10 ^ 9 + 7)。
所以,我尝试为此开发一个递归解决方案。但是,我无法添加约束以确保至少应存在权重d
的边缘。我怎样才能做到这一点?这是我的递归函数:
void calc(int present, int total,int k) // Here, present is initialised to 0.
// total is equal to n that is reqd.
// k is the value in the question
{
if (total == present)
{
ans++;
ans = ans%val;
return;
}
else
{
for ( int i = 1; i <= k; i++ )
{
if (present+i <= total)
return calc(present+i,total,k);
}
}
}
答案 0 :(得分:2)
只需在函数中添加以下参数 - d ,以及是否已达到其中一条边至少为d
的约束。
void calc(int present, int total,int k, int d, bool atleastd)
{
仅在atleastd
时将约束更改为增量。
if (total == present && atleastd)
{
ans++;
ans = ans%val;
return;
}
else
{
for ( int i = 1; i <= k; i++ )
{
if (present+i <= total)
当你递归调用你的函数时,如果你刚刚满足这个约束(atleastd
),则通过i >= d
之前是否已经实现,或。
calc(present+i,total,k,d,atleastd || i >= d);
此外,我删除了上一行中的return
。否则,代码将仅测试1个可能的路径 - 所有权重== 1的路径。
}
}
}
我假设ans
和val
是全局变量,ans
是问题的答案,初始化为0,val
是模数= 1000000007。
最后,虽然这个解决方案可以解决n <= 15
的小测试用例,但是对于n = 100来说它会太慢。
要解决n = 100,我建议您了解memoization和dynamic programming。我将把这作为练习留给你。