Problem link: https://www.acmicpc.net/problem/17435
Bounded Knapsack 문제를 log-step DP를 통해 0-1 Knapsack으로 풀어주는 아이디어를 활용하면 된다.
아래는 문제를 풀었던 사고의 흐름을 날 것 그대로 정리한 것이다.
O(n)
으로 곧이 곧대로 구해주면 당연히 TLE가 난다.F_n(x) = F_a(F_b(x)), where a + b = n
n
의 최대 값은 500000이므로, 2^0, 2^1, ..., 2^18
, 총 19개의 수를 활용하면 범위 내의 어떤 n
이건 유일하게 표현해줄 수 있다(2진법).CACHE[i][x]: F_2^i(x)
CACHE[i+1][x] = CACHE[i][CACHE[i][x]]
#include <cstdio>
using namespace std;
const int kMaxM = 200000;
const int kMaxN = 500000;
const int kMaxExp = 18; // 2^19 -1 > 500000
int CACHE[kMaxExp + 1][kMaxM + 1];
int M;
int Q;
int Solve(const int n, const int x)
{
int ret = x;
for (int bitpos = 0; bitpos <= kMaxExp; ++bitpos)
{
if (n & (1 << bitpos))
{
ret = CACHE[bitpos][ret];
}
}
return ret;
}
int main(void)
{
// Read inputs
scanf(" %d", &M);
for (int it = 1; it <= M; ++it)
{
scanf(" %d", &CACHE[0][it]);
}
// DP
for (int e = 1; e <= kMaxExp; ++e)
{
for (int x = 1; x <= kMaxM; ++x)
{
CACHE[e][x] = CACHE[e - 1][CACHE[e - 1][x]];
}
}
// Process queries
scanf(" %d", &Q);
for (int it = 0; it < Q; ++it)
{
int n, x;
scanf(" %d %d", &n, &x);
printf("%d\n", Solve(n, x));
}
return 0;
}