Codeforces Round 1014 (Div. 2)
A. Kamilka and the Sheep
Kamilka 有 \(n\) 只羊,第 \(i\) 只羊的美丽值为 \(a_i\)(所有 \(a_i\) 互不相同)。早晨喂食时,Kamilka 可以选择一个非负整数 \(d\),给每只羊增加 \(d\) 的美丽值。傍晚,她必须选择恰好两只羊,其经过喂食后的美丽值分别为 \(x\) 和 \(y\)。Kamilka 的快乐值为 \(\gcd(x, y)\),求最大可能的快乐值。
\(n \leq 100, a_i \leq 10^9\)
对于两个正整数 \(i,j(i<j)\),\(\gcd (i,j) \leq j - i\),并且一定能找到一个 \(d\) 使得 \(i + d = k(j - i)\),此时 \(\gcd (i + d, j + d) = j - i\),答案为数组最大值减去最小值。
代码
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
const int N = 2000086, MOD = 998244353, INF = 0x3f3f3f3f;
ll res;
int n, m, cnt, w[N];
int main() {
int T;
cin >> T;
while (T--) {
cin >> n;
for (int i = 1; i < n + 1; i++) scanf("%d", w + i);
sort(w + 1, w + n + 1);
printf("%d\n", w[n] - w[1]);
}
return 0;
}
B. Lady Bug
Dasha Purova 一踏入法国国境,就被恶棍 Markaron 绑架,并关进了他那座大城堡下的监狱。幸运的是,听闻 Dasha 消息的美丽 Lady Bug 立即赶往 Markaron 城堡去救她。然而,为了进入城堡,她需要破解一个复杂的密码。该密码由两个长度为 \(n\) 的二进制串 \(a\) 和 \(b\) 组成。Lady Bug 可以进行任意次数的操作,每次操作中她可以选择任一索引 \(2 \le i \le n\),并执行下列两种操作之一:
- 交换 \(a_i\) 与 \(b_{i-1}\) 的值,即执行 \(swap(a_i,\, b_{i-1})\),
- 交换 \(b_i\) 与 \(a_{i-1}\) 的值,即执行 \(swap(b_i,\, a_{i-1})\)。
当 Lady Bug 能够使得字符串 \(a\) 全部变为 \(0\) 时,密码即被破解。请判断她是否有可能成功救出不幸的 Dasha。
\(n \leq 2 \times 10^5\)
交换操作实际使得 \(a\) 中奇数位置和 \(b\) 中偶数位置以及 \(a\) 中的偶数位置和 \(b\) 中的奇数位置可以任意交换,判断能否将 \(a\) 中所有 \(1\) 交换到 \(b\) 即可。
代码
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
const int N = 2000086, MOD = 998244353, INF = 0x3f3f3f3f;
ll res;
int n, m, cnt, w[N];
char a[N], b[N];
void solve() {
int c1 = 0, c2 = 0;
for (int i = 1; i < n + 1; i++) {
if (a[i] == '1') {
c1 += i & 1;
c2 += i & 1 ^ 1;
}
if (b[i] == '1') {
c1 += i & 1 ^ 1;
c2 += i & 1;
}
}
puts(c1 > n / 2 || c2 > (n + 1) / 2 ? "NO" : "YES");
}
int main() {
int T;
cin >> T;
while (T--) {
cin >> n;
scanf("%s%s", a + 1, b + 1);
solve();
}
return 0;
}
C. Asuna and the Mosquitoes
Asuna 的 \(n\) 位崇拜者在她生日时各送了她一座塔,第 \(i\) 位崇拜者送的塔高为 \(a_i\)。Asuna 认为这些礼物的美丽值为 \(\max(a_1, a_2, \dots, a_n)\)。她可以进行任意次数(也可以为 \(0\))如下操作:
- 选择任意两个下标 \(1 \le i \ne j \le n\),如果 \(a_i + a_j\) 是奇数,且 \(a_i > 0\)
那么将 \(a_i\) 减 \(1\),同时将 \(a_j\) 加 \(1\)。显然,在操作过程中塔的高度始终保持非负。请帮 Asuna 计算,在进行任意次数操作后,礼物可能达到的最大美丽值是多少。
\(n \leq 2 \times 10^5, a_i \leq 10^9\)
如果数组只有奇数或者只有偶数,显然一次操作也无法执行。
对于既有奇数也有偶数的情况,首先操作是不会改变数组中奇数的个数的,如果数组所有值的总和为 \(sum\),奇数个数为 \(cnt\),那么操作后的最大值一定小于等于 \(sum - cnt + 1\)。对于一个奇数 \(a_i\) 和一个偶数 \(a_j\),可以通过 \(a_j\) 次操作使把偶数全部加到奇数上,或者通过 \(a_i - 1\) 操作把奇数变成 \(1\),剩余的加到偶数上,因此我们可以先把所有奇数加到偶数上,再把所有偶数加到一个奇数上,此时可以取到最大值 \(sum - cnt + 1\)。
代码
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
const int N = 2000086, MOD = 998244353, INF = 0x3f3f3f3f;
ll res;
int n, m, cnt, w[N];
void solve() {
sort(w + 1, w + n + 1);
bool flag1 = 0, flag2 = 0;
for (int i = 1; i < n + 1; i++) flag1 |= w[i] & 1, flag2 |= w[i] & 1 ^ 1;
if (!flag1 || !flag2) {
printf("%d\n", w[n]);
return;
}
res = 0;
for (int i = 1; i < n + 1; i++) {
if (w[i] & 1) res += w[i] - 1;
else res += w[i];
}
res++;
printf("%lld\n", res);
}
int main() {
int T;
cin >> T;
while (T--) {
cin >> n;
for (int i = 1; i < n + 1; i++) scanf("%d", w + i);
solve();
}
return 0;
}
D. Mishkin Energizer
Edmond 正在为与老友 Fernan 的决斗做准备,他研发了一款名为 “Mishkin Energizer” 的能量饮料。饮料由一个长度为 \(n\) 的字符串 \(s\) 构成,字符串仅包含字符 L、I 和 T,分别代表饮料中三种不同成分的含量。如果饮料中三种成分的数量相等,则称该饮料为平衡饮料。为了增强气场并确保决斗胜利,Edmond 必须通过以下操作使初始字符串变为平衡状态:
- 选择一个索引 \(i\),满足 \(s_i \ne s_{i+1}\)(且 \(i+1\) 不超过字符串当前长度
- 在 \(s_i\) 与 \(s_{i+1}\) 之间插入一个字符 \(x\)(字符 \(x\) 可以是 L、I 或 T),要求 \(x \ne s_i\) 且 \(x \ne s_{i+1}\)。
请帮助 Edmond 在不超过 \(2n\) 次操作内使饮料平衡。如果存在多种方案,输出任一方案;如果不可能实现,则报告这一情况。
\(n \leq 100\)
如果只有一种字符,显然无法平衡。否则每次选择数量最小且有位置可以插入的字符进行操作即可。
代码
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
const int N = 2000086, MOD = 998244353, INF = 0x3f3f3f3f;
ll res;
int n, m, cnt, w[N];
char s[N];
void solve() {
int c1 = 0, c2 = 0, c3 = 0;
for (int i = 1; i < n + 1; i++) c1 += s[i] == 'L', c2 += s[i] == 'I', c3 += s[i] == 'T';
if (c1 == n || c2 == n || c3 == n) {
puts("-1");
return;
}
vector<char> v;
vector<int> ans;
for (int i = 1; i < n + 1; i++) v.push_back(s[i]);
int c = max({c1, c2, c3});
while (c1 < c || c2 < c || c3 < c) {
if (ans.size() > 2 * n) break;
bool flag = 0;
if (c1 < c) {
for (int i = 0; i < v.size() - 1; i++) {
if (v[i] != v[i + 1] && v[i] != 'L' && v[i + 1] != 'L') {
v.insert(v.begin() + i + 1, 'L');
ans.push_back(i + 1);
c1++;
flag = 1;
break;
}
}
}
if (c2 < c) {
for (int i = 0; i < v.size() - 1; i++) {
if (v[i] != v[i + 1] && v[i] != 'I' && v[i + 1] != 'I') {
v.insert(v.begin() + i + 1, 'I');
ans.push_back(i + 1);
c2++;
flag = 1;
break;
}
}
}
if (c3 < c) {
for (int i = 0; i < v.size() - 1; i++) {
if (v[i] != v[i + 1] && v[i] != 'T' && v[i + 1] != 'T') {
v.insert(v.begin() + i + 1, 'T');
ans.push_back(i + 1);
c3++;
flag = 1;
break;
}
}
}
if (!flag) {
if (c1 <= max(c2, c3)) {
for (int i = 0; i < v.size() - 1; i++) {
if (v[i] != v[i + 1] && v[i] != 'L' && v[i + 1] != 'L') {
v.insert(v.begin() + i + 1, 'L');
ans.push_back(i + 1);
c1++;
goto NE;
}
}
}
if (c2 <= max(c1, c3)) {
for (int i = 0; i < v.size() - 1; i++) {
if (v[i] != v[i + 1] && v[i] != 'I' && v[i + 1] != 'I') {
v.insert(v.begin() + i + 1, 'I');
ans.push_back(i + 1);
c2++;
goto NE;
}
}
}
if (c3 <= max(c1, c2)) {
for (int i = 0; i < v.size() - 1; i++) {
if (v[i] != v[i + 1] && v[i] != 'T' && v[i + 1] != 'T') {
v.insert(v.begin() + i + 1, 'T');
ans.push_back(i + 1);
c3++;
goto NE;
}
}
}
NE:;
c = max({c1, c2, c3});
}
}
if (ans.size() > 2 * n) {
puts("-1");
return;
}
printf("%d\n", ans.size());
for (auto u : ans) printf("%d\n", u);
}
int main() {
int T;
cin >> T;
while (T--) {
cin >> n;
scanf("%s", s + 1);
solve();
}
return 0;
}
E. She knows...
D. Pippy 正在为他家举办的“黑白派对”做准备。他只需要重新粉刷地下室的地板,该地板可以表示为一个大小为 \(n \times m\) 的棋盘。在上次派对之后,除了一些 \(k\) 个细胞 \((x_1, y_1), (x_2, y_2), \dots, (x_k, y_k)\) 外,整块棋盘都被漆成了绿色,每个给定的细胞已经被漆成黑色或白色。为了即将到来的派对,D. Pippy 想将剩下的绿色细胞重新涂成黑色或白色。同时,他希望重新粉刷后,棋盘上相邻颜色不同的细胞对数为偶数。
形式化地,设\[A = \{ ((i_1,j_1),(i_2,j_2)) \mid 1 \le i_1,i_2 \le n,\ 1 \le j_1,j_2 \le m,\ i_1+j_1 < i_2+j_2,\ |i_1-i_2|+|j_1-j_2| = 1,\ \text{color}(i_1,j_1) \ne \text{color}(i_2,j_2) \}, \]其中 \(\text{color}(x,y)\) 表示细胞 \((x,y)\) 的颜色,则要求 \(|A|\) 为偶数。
求有多少种方法可以重新粉刷地板使得上述条件满足。由于答案可能很大,请输出答案对 \(10^9+7\) 取模后的结果。
\(n,m \leq 10^9,k \leq 2 \times 10^5\)
两个格子的颜色不同实际上就是对两个格子的颜色进行异或操作,而在模 \(2\) 的意义下,异或是等价于加的,因此每个格子对 \(|A|\) 的贡献为这个格子的边数乘以格子颜色。一个格子如果有偶数条边,翻转这个格子不会影响 \(|A|\) 的奇偶性,因此我们只需要考虑边框上除去四个角的那些格子。统计边框未被染色的格子数量为 \(u\),非边框未被染色的格子数量为 \(t\),边框已染色格子的颜色和模 \(2\) 为 \(x\),如果 \(u\) 为 \(0\),若 \(x\) 为 \(1\),此时方案数为 \(0\),否则方案数为 \(2 ^ t\),如果 \(u\) 不为 \(0\),方案数为 \(2^{t+u-1}\)
代码
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
const int N = 2000086, MOD = 1e9 + 7, INF = 0x3f3f3f3f;
ll res;
int n, m, cnt, w[N];
inline ll qmi(ll a, ll b, ll c) { ll res = 1; while (b) { if (b & 1) res = res * a % c; a = a * a % c; b >>= 1; } return res; }
int k;
void solve() {
ll u = 0, v = 0;
int k;
cin >> n >> m >> k;
ll t = 2ll * ((n - 2) + (m - 2));
for (int i = 1; i < k + 1; i++) {
int x, y, c;
scanf("%d%d%d", &x, &y, &c);
if (x == 1 || x == n) {
if (y != 1 && y != m) u++, v ^= c;
} else if (y == 1 || y == m) {
u++, v ^= c;
} else {
}
}
t -= u;
ll in = (ll)n * m - k - t;
if (!t) {
if (!v) printf("%lld\n", qmi(2, in, MOD));
else puts("0");
} else {
printf("%lld\n", qmi(2, in + t - 1, MOD));
}
}
int main() {
int T;
cin >> T;
while (T--) {
solve();
}
return 0;
}