26牛客暑假多校5
点击查看题面
K题 Sequence(Mex Version)
题目大意
给定一个长度为
- 根据当前序列
构造一个新序列 ,其中 。这里 表示非负整数集合中最小的未出现的非负整数。 - 将序列
替换为 。
求经过
数据范围:
思路
值域缩减: 对于任意三个非负整数计算 ,其结果必然位于集合 中。因此,经过 次变换后,序列中的所有元素均会被限制在 的范围内。 - 周期性规律: 通过打表发现,序列在经历至多
次变换后,其状态转移将进入一个周期为 的稳定循环状态(即再做 次变换后,序列保持不变或在两个固定状态间循环切换)。 - 状态化简与模拟: 基于上述周期性,我们无需真正执行
次变换:
- 先令
,模拟前 次变换,将序列引导至稳定周期状态。 - 对于剩余的
次变换,由于周期为 ,只需判断 的奇偶性: - 若
为奇数,则额外再执行 次变换; - 若为偶数,则维持现状即可。
如此一来,序列变换的总次数被严格限制在至多
复杂度分析
时间复杂度:
空间复杂度:
参考代码
参考代码
c++
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int mex(int a, int b, int c) {
if (a != 0 && b != 0 && c != 0) return 0;
if (a != 1 && b != 1 && c != 1) return 1;
if (a != 2 && b != 2 && c != 2) return 2;
return 3;
}
void fc() {
int n, k;
cin >> n >> k;
vector<int> a(n);
for (int &i : a) {
cin >> i;
}
int d = min(3, k);
k -= d;
while (d--) {
vector<int> b(n);
for (int i = 0; i < n; i++) {
b[i] = mex(a[i], a[(i + 1) % n], a[(i + n - 1) % n]);
}
a = move(b);
}
if (k & 1) {
vector<int> b(n);
for (int i = 0; i < n; i++) {
b[i] = mex(a[i], a[(i + 1) % n], a[(i + n - 1) % n]);
}
a = move(b);
}
for (int i = 0; i < n; i++) {
cout << a[i] << (i == n - 1 ? "" : " ");
}
cout << "\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
// cin >> t;
while (t--) {
fc();
}
return 0;
}