题解-ARC077F

时间:2021-08-05
本文章向大家介绍题解-ARC077F,主要包括题解-ARC077F使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

神仙字符串结论题。

我们先进行一次操作变成一个 \(SS\) 串,然后考虑 \(S\) 的循环节 \(G\)

  1. \(G\)\(S\) 的整循环节

那么这个串会变成 \(SGSG\)\(SGGSGG\),...,\(SGGGG...SGGGG....\),由于是无限长我们只需考虑前半部分即可。这个直接求就行。

  1. \(G\) 不是 \(S\) 的整循环节

其实只是上一部分的扩展。

还是只用考虑前半部分,而前半部分的情况是 \(S_i=S_{i-1}+S_{i-2}\),也就是 \(S\)\(SG\)\(SGS\)\(SGSSG\)(其实样例已经给了提示)。

接下来我们来证明:

该结论等价于证明 \(SG\) 的最小循环节为 \(S\),且不会出现 \(G\) 变成整循环节的情况。设 \(SG=T\)

我们假设存在一个循环节 \(p\)\(S\) 更短,那么 \(p\) 也是 \(S\) 的循环节,所以 \(T[i]=T[i-p]\) 由于 \(G\)\(S\) 的前缀,所以 \(T[i]=T[i-|S|]\),又因为 \(G\) 是周期,所以 \(i-p\equiv i-|S|\pmod |G|\)\(|p|\equiv |S|\pmod |G|\),由于弱周期引理,\(S\) 有新的周期 \(\gcd(|p|,|G|)\),所以 \(p\)\(|G|\) 的倍数,所以 \(|S|\bmod |G|=0\) 矛盾!

于是我们直接暴力模拟即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2000005;
template <typename T>
void read(T &x) {
	T flag = 1;
	char ch = getchar();
	for (; !isdigit(ch); ch = getchar()) if (ch == '-') flag = -1;
	for (x = 0; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
	x *= flag;
}
char s[maxn];
int nxt[maxn];
ll l, r;
int n, m;
ll cnt[30], cntg[30], ans[30];
ll f[maxn];
ll cur[30], lst[30];
void solve(ll x, ll v) {
	if (x == 0) return;
	if (x <= n) {
		for (int i = 1; i <= x; i++) ans[s[i] - 'a'] += v;
	} else {
		x -= n;
		for (int i = 0; i < 26; i++) ans[i] = ans[i] + v * (cnt[i] + cntg[i] * (x / m));
		for (int i = 1; i <= x % m; i++) ans[s[i] - 'a'] += v;
	}
}
void dfs(ll x, ll v) {
	if (x <= 0) return;
	if (x <= n) {
		for (int i = 1; i <= x; i++) ans[s[i] - 'a'] += v;
		return;
	}
	f[1] = n, f[2] = n + m;
	int now = 2;
	for (int i = 0; i < 26; i++) cur[i] = cnt[i] + cntg[i], lst[i] = cnt[i];
	while (f[now] <= x) {
		if (now > 2) {
			for (int i = 0; i < 26; i++) {
				ll tmp = cur[i];
				cur[i] += lst[i];
				lst[i] = tmp;
			}
		}
		f[now + 1] = f[now] + f[now - 1];
		now++;
	}
	if (now == 2) {
		for (int i = 0; i < 26; i++) ans[i] += lst[i] * v;
		dfs(x - f[now - 1], v);
	} else {
		for (int i = 0; i < 26; i++) ans[i] += cur[i] * v;
		dfs(x - f[now - 1], v);
	}
}
int main() {
	scanf("%s", s + 1);
	read(l); read(r);
	n = strlen(s + 1);
	for (int i = 2, j = 0; i <= n; i++) {
		while (j && s[j + 1] != s[i]) j = nxt[j];
		if (s[j + 1] == s[i]) j++;
		nxt[i] = j;
	}
	int tmp = nxt[n];
	while (tmp >= (n + 1) / 2) {
		tmp = nxt[tmp];
	}
	n -= tmp;
	for (int i = 1; i <= n; i++) cnt[s[i] - 'a']++;
	m = n - nxt[n];
	for (int i = 1; i <= m; i++) cntg[s[i] - 'a']++;
	if (n % (n - nxt[n]) == 0) {
		solve(r, 1); solve(l - 1, -1);
		for (int i = 0; i < 26; i++) printf("%lld ", ans[i]);
	} else {
		dfs(r, 1); dfs(l - 1, -1);
		for (int i = 0; i < 26; i++) printf("%lld ", ans[i]);
	}
	return 0;
}

原文地址:https://www.cnblogs.com/zcr-blog/p/15106469.html