比赛链接:https://codeforces.com/contest/1549
A. Gregor and Cryptography
题解
构造。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
int p;
cin >> p;
cout << 2 << ' ' << (p - 1) << "
";
}
return 0;
}
B. Gregor and the Pawn Game
题解
贪心,尽可能地靠一边放。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<string> MP(2);
for (int i = 0; i < 2; i++) {
cin >> MP[i];
}
vector<bool> vis(n);
for (int i = 0; i < n; i++) {
if (MP[1][i] == '0') {
continue;
}
if (i - 1 >= 0 and MP[0][i - 1] == '1' and not vis[i - 1]) {
vis[i - 1] = true;
} else if (MP[0][i] == '0' and not vis[i]) {
vis[i] = true;
} else if (i + 1 < n and MP[0][i + 1] == '1' and not vis[i + 1]) {
vis[i + 1] = true;
}
}
cout << count(vis.begin(), vis.end(), true) << "
";
}
return 0;
}
C. Web of Lies
题解
类似拓扑排序的思想,将无向边转化为有向边,假设由较小点指向较大点,每次询问即统计出度为 0 的点。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
vector<int> out(n);
set<int> st;
auto opt = [&](bool add) {
int u, v;
cin >> u >> v;
--u, --v;
out[min(u, v)] += add ? 1 : -1;
st.erase(u), st.erase(v);
if (out[u] == 0) {
st.insert(u);
}
if (out[v] == 0) {
st.insert(v);
}
};
for (int i = 0; i < m; i++) {
opt(true);
}
for (int u = 0; u < n; u++) {
if (out[u] == 0) {
st.insert(u);
}
}
int q;
cin >> q;
while (q--) {
int op;
cin >> op;
if (op == 1) {
opt(true);
} else if (op == 2) {
opt(false);
} else {
cout << st.size() << "
";
}
}
return 0;
}
D. Integers Have Friends
题解
不妨先考察较小的情况,如果两个数 (a) 和 (b) 同余,它们与余数 (m) 的关系。
假设 (a lt b) ,易得:
(a = a)
(b = a + (b - a))
(a) 和 (b) 对 (m) 取余即:
(a mod m)
(a mod m + (b - a) mod m)
所以,若 (a) 和 (b) 同余,那么 ((b - a) mod m = 0) ,即 (m) 为 ((b - a)) 的因子。
推广到 (n) 个数同余的情况,可以看作 (n - 1) 对相邻的数, (m) 同为 (n - 1) 对相邻数之差的因子。
所以,问题即转化成了在 (b_i = |a_{i + 1} - a_i|) 中寻找 (gcd gt 1) 的最长区间。
可以枚举区间的左端点,然后用双指针或二分结合 (st) 表计算区间的右端点。
代码一
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<long long> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
if (n == 1) {
cout << 1 << "
";
continue;
}
vector<long long> b(n - 1);
for (int i = 0; i < n - 1; i++) {
b[i] = abs(a[i + 1] - a[i]);
}
const int logn = __lg(n) + 1;
vector<vector<long long>> spt(n - 1, vector<long long> (logn));
for (int i = 0; i < n - 1; i++) {
spt[i][0] = b[i];
}
for (int j = 1; j < logn; j++) {
for (int i = 0; i + (1 << j) - 1 < n - 1; i++) {
spt[i][j] = gcd(spt[i][j - 1], spt[i + (1 << (j - 1))][j - 1]);
}
}
auto query = [&](int l, int r) {
int ep = __lg(r - l + 1);
return gcd(spt[l][ep], spt[r - (1 << ep) + 1][ep]);
};
int ans = 0;
for (int i = 0, j = -1; i < n - 1; i++) {
while (j + 1 < n - 1 and query(i, j + 1) > 1) {
++j;
}
if (i <= j) {
ans = max(ans, j - i + 1);
}
j = max(j, i);
}
cout << ans + 1 << "
";
}
return 0;
}
代码二
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<long long> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
if (n == 1) {
cout << 1 << "
";
continue;
}
vector<long long> b(n - 1);
for (int i = 0; i < n - 1; i++) {
b[i] = abs(a[i + 1] - a[i]);
}
const int logn = __lg(n) + 1;
vector<vector<long long>> spt(n - 1, vector<long long> (logn));
for (int i = 0; i < n - 1; i++) {
spt[i][0] = b[i];
}
for (int j = 1; j < logn; j++) {
for (int i = 0; i + (1 << j) - 1 < n - 1; i++) {
spt[i][j] = gcd(spt[i][j - 1], spt[i + (1 << (j - 1))][j - 1]);
}
}
auto query = [&](int l, int r) {
int ep = __lg(r - l + 1);
return gcd(spt[l][ep], spt[r - (1 << ep) + 1][ep]);
};
int ans = 0;
for (int i = 0; i < n - 1; i++) {
int l = i, r = n - 2;
while (l < r) {
int mid = (l + r + 1) / 2;
if (query(i, mid) > 1) {
l = mid;
} else {
r = mid - 1;
}
}
if (query(i, r) > 1) {
ans = max(ans, r - i + 1);
}
}
cout << ans + 1 << "
";
}
return 0;
}