安吉D5-T2
- 1安吉D19 T1
- 2安吉D19 T3
- 3安吉D20 模考12总结
- 4安吉D17 T3
- 5安吉D17 T4
- 6安吉D19 模考11总结
- 7安吉D15 A
- 8安吉D16 T4
- 9安吉D17 T1
- 10安吉D17 模考10总结
- 11安吉D16 T3
- 12安吉D16 模考9总结
- 13安吉D13 模考8总结
- 14安吉D13-T2
- 15安吉D13-T3
- 16安吉D12-T3
- 17安吉D11-B
- 18安吉D11-C
- 19安吉D11-D
- 20安吉D12 模考7总结
- 21安吉D12-T2
- 22安吉D11-A
- 23安吉D10 模考6总结
- 24安吉D10-T3
- 25安吉D10-T4
- 26安吉D8-E
- 27安吉D9-T4
- 28安吉D8-A
- 29安吉D8-B
- 30安吉D8-C
- 31安吉D8-D
- 32安吉D9 模考5总结
- 33安吉D9-T2
- 34安吉D9-T3
- 35安吉D6-T4
- 36安吉D4-G
- 37安吉D5-T2本文
- 38安吉D6 模考4总结
- 39安吉D6-T1
- 40安吉D6-T3
- 41安吉-开营测试 T4
- 42安吉D5 模考3总结
- 43安吉D5-T3
- 44安吉D4-A
- 45安吉D4-B
- 46安吉D4-C
- 47安吉D4:容斥原理
- 48安吉Day4-D
- 49安吉D3 模考2总结
- 50安吉D3-T1
- 51安吉D3-T2
- 52安吉D3-T4
- 53安吉D2 模考1总结
- 54安吉D2-T2
- 55安吉D1-G
- 56安吉D1-L
- 57安吉D2-T4
原题呈现
题目描述
给定一个长度为 的环形序列 .
其中每个位置的值满足:
- 若 ,表示第 个位置尚未确定;
- 若 ,表示第 个位置已经确定为编号 的灵魂宝石.
你需要将所有值为 的位置填上剩余未出现的数字,使得最终序列成为一个 到 的排列.
对于一个非负整数 ,定义 表示 的二进制表示中 的个数.
对于最终排列中一对相邻位置上的数字 ,如果 与 的奇偶性不同,则称这对相邻数字达成了平衡.
其中 表示按位与, 表示按位或.
由于序列是环形的, 也相邻.
如果最终排列中的所有相邻数字对都达成了平衡,则称这个排列符合圆环之理.
现在有 次观测修改.每次修改会将某个位置的值改为一个新的值,新的值可以是 ,也可以是 到 之间的整数.
请你分别求出初始状态以及每次修改之后,当前序列可以补全为符合圆环之理的排列数量.
两个补全方案不同,当且仅当至少存在一个位置,在两个最终排列中的数字不同.
答案对 取模.
输入格式
第一行包含两个整数 ,表示圆环长度和观测修改次数.
第二行包含 个整数 ,表示初始圆环状态.
接下来 行,每行包含两个整数 ,表示一次观测修改:将 修改为 .
输出格式
输出 行.
第一行输出初始状态下的答案.
接下来第 行输出第 次修改后的答案.
样例
输入 #1
6 60 0 0 0 0 01 12 33 24 55 46 1输出 #1
721242110数据范围
本题采用捆绑评测,对于一个子任务,你必须通过其中的所有测试点才能得到对应分数.
| 子任务编号 | 分数 | 特殊性质 | |
|---|---|---|---|
| 1 | 10 | 无 | |
| 2 | 15 | 无 | |
| 3 | 15 | 无 | |
| 4 | 15 | ||
| 5 | 20 | 保证任意时刻,序列中存在不为 的位置 | |
| 6 | 25 | 无 |
对于全部数据:
- ;
- ;
- ;
- ;
- .
观察题意中平衡的条件:若两个数, 为奇数(根据题意,这里 等同于 ),则这两个数平衡.又由于 ,所以题意中平衡的条件转化为:
奇偶性不同的两个数相互平衡.
记 结果为奇数的正整数集合为 ,称其为一类数,结果为偶数的正整数集合是 ,称其为二类数,则合法序列必须满足:一类数(和 0)和二类数(和 0)交错排列,因此, 必须等于 ,否则就始终没有合法的方案.
定义 ,,表示在已知序列中, 满足是一类数(若 )或是二类数(若 )、且处于奇数()或偶数()位置的正整数的数量.
先遍历整个已知的序列,计算出 ,再判断以下条件是否成立:
- 没有重复的正整数
- 不存在 ,满足 和 都不为 0.(保证不会有两个 奇偶性相同的数,一个在奇数位置上,一个在偶数位置上)
如果存在任意一个条件不成立,无解,输出 0.
否则,令 表示已知序列二类数数量,.令 表示已知序列中一类数数量,.
则存在 个可以自由分配位置的一类数,存在 个可以自由分配位置的二类数,最终结果为 .
特别的,若所有数字都是 0(),则一类数和二类数可以整体交换位置,答案要乘 2.
当需要修改时,只需要动态维护 数组,再维护每一个数字出现几次(用于检查是否重复)即可.
标程
#include <bits/stdc++.h>#define group(x) (__builtin_popcountll(x) % 2)// 该内建函数(__builtin_popcount)可以计算一个数二进制表示中1的数量using namespace std;typedef long long ll;const int N = 2e5 + 100;const int MOD = 998244353;int n, q, a[N], fac[N];int c[2][2];int cnt1 = 0, cnt0 = 0;int rep = 0;map<int, int> used;// c[i][j] 表示当前序列中0/1类数在偶/奇位置上的一共有多少个.
int calFac(int x) { if (!fac[x]) { fac[x] = 1ll * calFac(x - 1) * x % MOD; } return fac[x];}
void solve() { if (!((c[0][0] == 0 && c[1][1] == 0) || (c[0][1] == 0 && c[1][0] == 0))) { cout << 0 << endl; return; } int unused0 = cnt0 - (c[0][1] + c[0][0]); int unused1 = cnt1 - (c[1][1] + c[1][0]); ll ans = 1ll * calFac(unused0) * calFac(unused1) % MOD; if (c[0][1] + c[0][0] + c[1][1] + c[1][0] == 0) { (ans *= 2) %= MOD; } cout << ans << endl;}
int main() {#ifdef ONLINE_JUDGE freopen("circle.in", "r", stdin); freopen("circle.out", "w", stdout);#endif cin >> n >> q; fac[0] = 1; for (int i = 1; i <= n; i++) { cin >> a[i]; if (used[a[i]] != 0 && a[i] != 0) { rep++; } used[a[i]]++; if (a[i] != 0) c[group(a[i])][i % 2]++; } for (int i = 1; i <= n; i++) { if (group(i)) { cnt1++; } else { cnt0++; } } if (cnt1 != cnt0) { for (int i = 0; i <= q; i++) { cout << 0 << endl; } return 0; } if (!rep) solve(); else cout << 0 << endl; for (int i = 1; i <= q; i++) { int p, x; cin >> p >> x; if (a[p]) { c[group(a[p])][p % 2]--; used[a[p]]--; } if (used[a[p]] == 1) { rep--; } a[p] = x; if (x) { c[group(x)][p % 2]++; used[x]++; } if (used[x] == 2) { rep++; } if (rep) { cout << 0 << endl; continue; } solve(); }}文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!


