Codeforces Round 981 (Div. 3) 题解
A
人类检测器。
手推不难发现,奇数都在负半轴,偶数都在正半轴,然后判断奇偶就行了。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
void solve () {
int n; cin >> n;
if (n & 1) cout << "Kosuke\n";
else cout << "Sakurako\n";
}
int main () {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int _ = 1; cin >> _;
while (_--) solve();
return 0;
}
B
纯模拟题,直接模拟正方形的每一个对角线,在每一条对角线上取绝对值最大的负数即可。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
void solve () {
int n; cin >> n;
vector <vector <int> > a(n, vector<int>(n));
for (int i = 0;i < n;i++)
for (int j = 0;j < n;j++)
cin >> a[i][j];
ll ans = 0;
for (int i = 0;i < n;i++) {
int x = i, y = 0;
int tmp = 0;
while (x < n && y < n) {
if (a[x][y] < 0) tmp = max(tmp, abs(a[x][y]));
x++, y++;
}
ans += tmp;
}
for (int j = 1;j < n;j++) {
int x = 0, y = j, tmp = 0;
// cout << x << " " << n << "\n";
while (x < n && y < n) {
if (a[x][y] < 0) tmp = max(tmp, abs(a[x][y]));
// cout << "[+] " << x << " " << y << "\n";
x++, y++;
}
ans += tmp;
}
cout << ans << "\n";
}
int main () {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int _ = 1; cin >> _;
while (_--) solve();
return 0;
}
C
被自己的脑子小坑了一把,这里可以直接先得到交换前的答案和交换后的答案,然后比较,看看哪个更优进行操作就行。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
void solve () {
int n; cin >> n;
vector <int> a(n+1);
for (int i = 1;i <= n;i++) cin >> a[i];
ll ans = 0;
int mid = (n+1)/2;
for (int i = 2;i <= mid;i++) {
int pre = (a[i] == a[i-1]) + (a[n-i+1] == a[n-i+2]);
int nex = (a[i] == a[n-i+2]) + (a[i-1] == a[n-i+1]);
if (nex < pre) swap(a[i], a[n-i+1]);
}
for (int i = 1;i < n;i++) if (a[i] == a[i+1]) ans++;
cout << ans << "\n";
}
int main () {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int _ = 1; cin >> _;
while (_--) solve();
return 0;
}
D
个人觉得这个比 C 简单。
这个可以直接贪心,利用前缀和统计,然后对于每一种前缀和记录它最近上一次的出现位置,然后判断这个位置会不会和目前最右边的区间重叠,随后统计答案就行了。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
const int N = 1e5+100;
// int a[N], sum[N];
void solve () {
int n; cin >> n;
vector <ll> a(n+2), sum(n+2);
map <ll, ll> pos;
for (int i = 1;i <= n;i++) {
cin >> a[i];
if (i == 1) sum[i] = a[i];
else sum[i] = sum[i-1] + a[i];
pos[sum[i]]= -1;
}
pos[0] = 0;
int maxr = -1;
ll ans = 0;
// for (int i = 1;i <= n;i++) cout << sum[i] << " ";
// cout << "n";
for (int i = 1;i <= n;i++) {
if (pos[sum[i]] == -1) pos[sum[i]] = i;
else {
int l = pos[sum[i]];
// cout << "[+] " << sum[i] << "===> " << l << "----"
// << maxr << 'n';
if (l >= maxr) ans++, maxr = i;
pos[sum[i]] = i;
}
}
cout << ans << "\n";
}
int main () {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int _ = 1; cin >> _;
while (_--) solve();
return 0;
}
E
绷,这题考并查集的考法的确新颖。
我们思考一下题目给出的两个条件:
\[p_i = i \\ p_{p_i} = i
\]
具体点来说:
-
位置上是自己。
-
位置上的数字和另一个位置上的数字对换了。
如果用图的思维来想,那么一个是自环一个就是两个节点组成的循环。
同时我们知道这是一个排列,试着将位置上的值和位置的编号建立一个有向边,发现最后是一定可以变成若干个环。而已经说过了合法的情况只有上面两种,基于贪心,我们选择第二种,不难发现,我们设每个连通块的大小为 \(size_i\),那么我们只需要变更 \(\lfloor \frac{size_i-1}{2}\rfloor\) 次,因为最后一队会在最后自己合法。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
void solve () {
int n; cin >> n;
vector <int> p(n+1), fa(n+1), si(n+1);
for (int i = 1;i <= n;i++) si[i] = 1, fa[i] = i;
auto find = [&](auto self, int a) -> int {
if (fa[a] == a) return a;
return fa[a] = self(self, fa[a]);
};
auto merge = [&](int a, int b) -> void {
int faa = find(find, fa[a]), fab = find(find, fa[b]);
if (faa != fab) {
// fa[faa] = fab;
if (si[faa] < si[fab]) swap(si[faa], si[fab]);
si[faa] += si[fab];
fa[fab] = faa;
}
};
for (int i = 1;i <= n;i++) {
cin >> p[i];
merge(p[i], i);
}
ll ans = 0;
for (int i = 1;i <= n;i++)
if (fa[i] == i) ans += (si[i]-1)/2;
cout << ans << "\n";
}
int main () {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int _ = 1; cin >> _;
while (_--) solve();
return 0;
}
F
逆天数论题,讨论的是斐波那契数列的模数周期性,其实就是皮亚诺定理,但是我真的不会QWQ,也是请教别人得到的。
给出几个连接大家学习学习:皮亚诺定理
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
const int N = 1e6+100;
const int MOD = 1e9+7;
int f[N];
void solve () {
ll n, k; cin >> n >> k;
f[1] = f[2] = 1;
ll p = 0; int i = 3;
while (1) {
f[i] = (f[i-1] + f[i-2]) % k;
if (!f[i]) { p = i; break; }
i++;
}
if (k == 1) p = 1;
cout << (n % MOD) * (p % MOD) % MOD << "\n";
}
int main () {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int _ = 1; cin >> _;
while (_--) solve();
return 0;
}
浙公网安备 33010602011771号