CF889E Mod Mod Mod
一道有趣的题,考虑\(x\)有意义的取值,设\(f_i\)表示\(x \bmod a_1 ... \bmod a_i\)的值,那么一定存在\(f_k = a_k - 1\),否则我们可以让\(x\)整体加一直到达到上界,这样显然更优,所以\(x\)有意义的取值只有\(O(n)\)个,这样我们可以\(DP\)去维护这些取值的答案。具体的,设\(g_{i,j}\)表示到第\(i\)轮,在\(\bmod a_i\)后的值为\(j\)高于当前数的和,这样答案就为\(g_{i,j} + ij\)。
\[g_{i+1,j \bmod a_{i + 1}} = \max{g_{i,j} + i * (j - j \bmod a_{i + 1})} \]\[g_{i+1,a_{i+1} - 1} = \max{g_{i,j} + i * ((j + 1) / a_{i+1} * a_{i + 1} - a_{i+1})} \]用\(map\)来转移\(DP\)。
Code
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<map>
#define LL long long
#define IN inline
using namespace std;
const int N = 2e5 + 5;
int n; LL a[N];
IN LL read() {
LL res = 0; char ch = getchar();
for (; !isdigit(ch); ch = getchar());
for (; isdigit(ch); ch = getchar()) res = (res << 3) + (res << 1) + (LL)(ch ^ 48);
return res;
}
map<LL, LL> f;
int main() {
n = read();
for (LL i = 1; i <= n; i++) a[i] = read();
f[a[1] - 1] = 0;
for (int i = 2; i <= n; i++) {
for (auto j = f.lower_bound(a[i]); j != f.end(); f.erase(j++)) {
LL v = j->first % a[i], g = j->first;
f[v] = max(f[v], j->second + (LL)(i - 1) * (g - v));
f[a[i] - 1] = max(f[a[i] - 1], j->second + (LL)(i - 1) * ((g + 1) / a[i] * a[i] - a[i]));
}
}
LL ans = 0;
for (auto i : f) ans = max(ans, i.second + (LL)n * i.first);
printf("%lld\n", ans);
}