AtCoder Grand Contest 003E 题解

【Problem】

Statement:

pro

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;
}
posted @ 2020-09-04 16:57  Beginner2670  阅读(106)  评论(0)    收藏  举报