Ссылка на вопрос: http://codeforces.com/problemset/problem/431/C
Совсем недавно творческая ученица Леша провела лекцию по деревьям. После
лекция леша была вдохновлена и придумала собственное дерево
который он назвал к-деревом.K-дерево — это бесконечное корневое дерево, где:
- каждая вершина имеет ровно k детей;
- каждый край имеет некоторый вес;
- если мы посмотрим на ребра, идущие от некоторой вершины к ее дочерним элементам (точно
k ребер), то их веса будут равны 1, 2, 3, …, k.На рисунке ниже показана часть 3-х деревьев.
Как только Дима, хороший друг Леши, узнал о дереве, он
Сразу задумался: «Сколько дорожек общего веса n (сумма
все веса ребер в пути), начиная с
корень k-дерева, а также содержащий по крайней мере один край веса в
хотя бы д? ». Помогите Диме найти ответ на свой вопрос. По количеству
пути могут быть довольно большими, выведите его по модулю 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);
}
}
}
Просто добавьте следующие аргументы к вашей функции — 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, я предлагаю узнать о мемоизации а также динамическое программирование. Я оставлю это как упражнение для вас.
Других решений пока нет …