AtCoder Grand Contest 003E 题解
【Problem】
Statement:
Solution:
考虑对于操作\(i<j\)且\(q_i>q_j\)的这些\(i\)操作都是无效的,一定会被后面的操作截断。删除无效操作,使得\(q_i\)单调递增。但是好像还是没有办法正着做,于是考虑倒着做。考虑把最后一个操作用前面的段进行覆盖。记\(o_i\)表示第\(i\)个有效段在最后一段上完整地出现的次数。显然有以下转移:\(o_{i}\gets o_{i+1}\times \frac{q_{i+1}}{q_i}\),对于余数,可以不断寻找前面的小段进行覆盖,并更新答案。
Code
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1.5E5;
long long o[MAXN];
long long ans[MAXN];
long long seq[MAXN];
int top, n, q;
long long a;
void getAns(long long len, long long value)
{
int bestPos = upper_bound(seq + 1, seq + 1 + top, len) - seq - 1;
if (!bestPos)
return ans[1] += value, ans[len + 1] -= value, void();
o[bestPos] += value * (len / seq[bestPos]), getAns(len % seq[bestPos], value);
}
int main(void)
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> q;
seq[++top] = n;
for (int i = 1;i <= q; ++i)
{
cin >> a;
while (top && seq[top] >= a)
--top;
seq[++top] = a;
}
o[top] = 1;
for (int i = top - 1; i; --i)
o[i] += o[i + 1] * (seq[i + 1] / seq[i]), getAns(seq[i + 1] % seq[i], o[i + 1]);
ans[1] += o[1], ans[seq[1] + 1] -= o[1];
for (int i = 1;i <= n; ++i)
ans[i] += ans[i - 1], cout << ans[i] << '\n';
return 0;
}

浙公网安备 33010602011771号