Problem Statement
有 (N) 张卡片,从左到右按 (1sim N) 编号,你会做如下操作:
- 将所有从左到右第 (Kx + 1) 张卡片盖章。
- 将这些被盖章的卡片删除。
求出最后一张被删除的卡片的编号。
给定 (K) 和 (Q) 个 (N) ,对于每个 (N) 求出答案。
Constraints
(1le K le 10 ^ 4) ,(1le Q le 10 ^ 5) ,(1le N le 10 ^ {18}) 。
Solution
设答案为 (f_n) ,那么有递推式:
[egin{cases}
f_1 = 1 \
f_n = f_{n - lceilfrac{n}{K}
ceil} + leftlceilfrac{f_{n - lceilfrac{n}{K}
ceil}}{K - 1}
ight
ceil \
end{cases}
]
其中 (n - lceilfrac{n}{K} ceil) 是每一轮剩下的个数,(leftlceilfrac{f_{n - lceilfrac{n}{K} ceil}}{K - 1} ight ceil) 是在 (n) 的情况下,(n - lceilfrac{n}{K} ceil) 的这个位置前面被删去的个数。
然后获得了一个 (mathcal O (n)) 的算法。
然后一搞这个柿子,容易发现这是单调递增的,每个相同数字的端点比较稀疏。
设每个端点的位置为 (X_i) ,即对于所有 (f_k = i) ,有 (X_i le k < X_{i + 1}) 。
然后考虑每个 (X_{i + 1}leftarrow X_{i}) 的过程,考虑每个 (X_i) 能转移到的位置的范围,然后得出:
[X_{i + 1} - leftlceilfrac{X_{i + 1}}{K}
ight
ceil = X_i
]
由于都会初中数学,所以得到:
[KX_i le (K - 1) X_{i + 1} < (K + 1) X_i
]
然后就有:
[egin{cases}
X_1 = 1 \
X_n = X_{n - 1} + leftlceilfrac{X_{n - 1}}{K - 1}
ight
ceil
end{cases}
]
这显然是对的。
然后分析一下算 (X) 的复杂度,对于一个巨大的 (n) ,(X_{i + 1}ge (1 + frac{1}{K - 1})X_i) ,所以 (T(n) le 1 + log_{(1 + frac{1}{K - 1})} n le 1 + klog n) 。
最神奇的是这两个东西的递推式是一样的。
int K, Q; i64 n, X[N], F[N], num;
inline i64 CiL(i64 A, i64 B) {
return (A + B - 1) / B;
}
inline void solve() {
Rdn(K, Q);
X[++num] = 1, F[num] = 1;
while (X[num] < 1e18) X[num + 1] = X[num] + CiL(X[num], K - 1), ++num, F[num] = F[num - 1] + CiL(F[num - 1], K - 1);
while (Q--) {
Rdn(n);
Wtn(F[upper_bound(X + 1, X + num + 1, n) - X - 1], '
');
}
}