
C/C++
Как оптимизировать код, чтобы не было превышения по времени к задаче (C++, динамическое программирование)?
Задача (на изображении). Я написал к ней код, но он не проходит по времени (TL) на втором тесте. Мой алгоритм - динамика, где d[i][j] - кол-во, подходящих чисел длиной i и, оканчивающихся на цифру j и dp[i + 1][j] = сумма по всем хорошим d (то есть таким, что |d - j| лежит в отрезке от l до r) величин dp[i][d]. Хотел спросить, как оптимизировать код или, может быть, есть другой алгоритм, который эффективнее моего? Мой код на C++ -https://pastebin.com/G7yvWq1u. Заранее благодарю.


ты линейную алгебру знаешь?
хотя бы основы: векторы, матрицы, умножение матриц?
хотя бы основы: векторы, матрицы, умножение матриц?
Айрат Иматдинов
Да, основы знаю
> Мой алгоритм - динамика, где d[i][j] - кол-во, подходящих чисел длиной i
А ничего, что длина может быть 10^18? Памяти-то тебе хватит?
Здесь нужна какая-то жесткая математика, а не циклы или переборы любого вида. Думай в этом направлении.
А ничего, что длина может быть 10^18? Памяти-то тебе хватит?
Здесь нужна какая-то жесткая математика, а не циклы или переборы любого вида. Думай в этом направлении.
Айрат Иматдинов
Спасибо
Сделай динамику типа dp[длина числа] [последняя цифра] = кол-во таких цифр
Ну обновлять ее легко просто dp[n][c] = dp[n - 1][c + l] + dp[n - 1][c + l + 1] + .+ dp[n - 1][c + r] + dp[n - 1][c - l] + dp[n - 1][c - l - 1] + .+ dp[n - 1][c - r]
Ну обновлять ее легко просто dp[n][c] = dp[n - 1][c + l] + dp[n - 1][c + l + 1] + .+ dp[n - 1][c + r] + dp[n - 1][c - l] + dp[n - 1][c - l - 1] + .+ dp[n - 1][c - r]
Айрат Иматдинов
Спасибо огромное
Имхо, слишком много обращений к веркторам.
1) избавиться от двумерности; для работы достаточно 2 массива: для i и i-1 (фиксированного размера)
2) во снутреннем цикле сделать отдельную переменную-счётчик, которую записывать в массив после цикла
как-то так:
int prev [ 10 ], next [ 10 ];
for (int j = 10; --j >= 0; ) prev [ j ] = 1; // fill for i = 1
for (int i = 2; i <= n; ++i) {
for (int j = 0; j < 10; ++j) {
int cnt = 0;
for (int x = 0; x < 10; ++x) {
int d = x - j;
if (d < 0) d = -d;
if (d >= l && d <= r)
cnt = (cnt + prev [ x ]) % mod;
}
next [ j ] = cnt;
}
::memcpy (prev, next, sizeof (prev));
}
1) избавиться от двумерности; для работы достаточно 2 массива: для i и i-1 (фиксированного размера)
2) во снутреннем цикле сделать отдельную переменную-счётчик, которую записывать в массив после цикла
как-то так:
int prev [ 10 ], next [ 10 ];
for (int j = 10; --j >= 0; ) prev [ j ] = 1; // fill for i = 1
for (int i = 2; i <= n; ++i) {
for (int j = 0; j < 10; ++j) {
int cnt = 0;
for (int x = 0; x < 10; ++x) {
int d = x - j;
if (d < 0) d = -d;
if (d >= l && d <= r)
cnt = (cnt + prev [ x ]) % mod;
}
next [ j ] = cnt;
}
::memcpy (prev, next, sizeof (prev));
}
Айрат Иматдинов
Спасибо огромное
Айрат Иматдинов
Попробовал, теперь памяти затратилось не 114.62 мб, а всего лишь 184 кб, спасибо огромное еще раз. Но, к сожалению, по времени работы тоже превысило ограничение
Я Люблю Вас Мама И Папа
Чувак, посмотри на ограничения. Если не заходит - значит там просто решение плохое. Ты ещё б сказал быстрый ввод вывод сделать)
Похожие вопросы
- Как оптимизировать код, чтобы не было превышения по времени к задаче (C++)?
- Написать код для задачи C++
- Помогите с кодом задачи c++. задача на фото
- Задачи по динамической памяти. C++
- C++ динамический массив
- Задача на языке программирования C++
- Задача на языке программирования C#
- Задача на языке программирования C++
- Задача по языку программированию C++
- Помогите решить задачу C++