解题报告 ABC398
省流:1575pts,rk2219。
A.
显然直接把 = 构造到中间,\(n\) 是奇数时放一个 =,否则放两个 =。
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
const int maxn = 100 + 10;
int n;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n;
int x = n / 2;
if (n % 2)
{
for (int i = 1; i <= x; i++)
cout << '-';
cout << '=';
for (int i = 1; i <= x; i++)
cout << '-';
}
else
{
for (int i = 1; i <= x - 1; i++)
cout << '-';
cout << "==";
for (int i = 1; i <= x - 1; i++)
cout << '-';
}
return 0;
}
B.
只要统计是否存在两种牌 \(i,j\) 满足出现次数 \(cnt_i\ge 3,cnt_j\ge 2\) 就行。
实现上五花八门。这里选择开桶读入后进行排序。
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
const int maxn = 13 + 10;
int cnt[maxn];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
for (int i = 1; i <= 7; i++)
{
int x;
cin >> x;
cnt[x]++;
}
sort(cnt + 1, cnt + 13 + 1, [](int a, int b)
{ return a > b; });
if (cnt[1] >= 3 && cnt[2] >= 2)
cout << "Yes" << endl;
else
cout << "No" << endl;
return 0;
}
C.
读入时开桶标记 \(a_i\) 有重复的,然后直接扫一遍。
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
const int maxn = 300'000 + 10;
int n;
int a[maxn];
unordered_map<int, int> cnt;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
cnt[a[i]]++;
}
int maxa = -1, maxi = -1;
for (int i = 1; i <= n; i++)
{
if (cnt[a[i]] != 1)
continue;
if (a[i] > maxa)
{
maxa = a[i];
maxi = i;
}
}
cout << maxi << endl;
return 0;
}
D.
注意到让烟动的复杂度是不可承受的,所以我们反过来让人动,并记录到原点的偏移量来维护原点。
实现上可以使用 map<pair<int, int>, bool> 存储每一个位置是否有烟。这里不知道为什么用 unordered_map CE了。
但是怎么还有那么多人想不到这个存图方式。
E.
注意到一个没有奇环的图是二分图。
对图进行染色分为两个集合 \(A,B\),易知游戏结束时图中共有 \(|A|\times |B|\) 条边。由于原有 \(n-1\) 条边,总的操作次数 \(cnt=|A|\times|B|-n+1\)。
显然 \(cnt\) 为奇数时先手必胜,否则后手必胜。
对于加边操作,我们使用 set 存储所有可加的边,每次随机取出一条即可。这里取的是第一条。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 100 + 10;
int n;
vector<int> e[maxn];
bool g[maxn][maxn];
int col[maxn];
vector<int> a, b;
set<pair<int, int>> s;
void BFS(int u)
{
queue<int> Q;
col[u] = 0;
Q.push(u);
while (!Q.empty())
{
int u = Q.front();
Q.pop();
for (auto v : e[u])
if (col[v] == -1)
{
col[v] = col[u] ^ 1;
Q.push(v);
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n - 1; i++)
{
int u, v;
cin >> u >> v;
e[u].push_back(v);
e[v].push_back(u);
g[u][v] = g[v][u] = true;
}
memset(col, -1, sizeof col);
BFS(1);
for (int i = 1; i <= n; i++)
if (!col[i])
a.push_back(i);
else
b.push_back(i);
for (int i = 1; i < n; i++)
for (int j = i + 1; j <= n; j++)
{
if (col[i] != col[j] && g[i][j] == 0)
{
s.insert(make_pair(i, j));
s.insert(make_pair(j, i));
}
}
int cnt = a.size() * b.size() - n + 1;
if (cnt % 2)
{
cout << "First" << endl;
int u = (*s.begin()).first, v = (*s.begin()).second;
cout << u << " " << v << endl;
s.erase(make_pair(u, v));
s.erase(make_pair(v, u));
}
else
cout << "Second" << endl;
while (true)
{
int u, v;
cin >> u >> v;
if (u == -1 && v == -1)
break;
s.erase(make_pair(u, v));
s.erase(make_pair(v, u));
u = (*s.begin()).first, v = (*s.begin()).second;
cout << u << " " << v << endl;
s.erase(make_pair(u, v));
s.erase(make_pair(v, u));
}
return 0;
}
F.
注意到本质上是求一个最长后缀回文子串。
可以正逆序各求一遍哈希,然后暴力枚举这个子串的长度进行处理。
KMP 和马拉车好像也可做。反正随便乱搞一下就过掉了。
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int unsigned long long
const int maxn = 500000 + 10;
const int base = 13331;
string s, r;
int n;
int h1[maxn], h2[maxn];
int qpow(int a, int b)
{
int res = 1;
while (b > 0)
{
if (b & 1)
res = res * a;
a = a * a;
b >>= 1;
}
return res;
}
int get_hash1(int l, int r) { return h1[r] - h1[l - 1] * qpow(base, r - l + 1); }
int get_hash2(int l, int r) { return h2[l] - h2[r + 1] * qpow(base, r - l + 1); }
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> s;
n = s.size();
s = " " + s;
for (int i = 1; i <= n; i++)
r += s[i];
r = " " + r + " ";
for (int i = 1; i <= n; i++)
h1[i] = h1[i - 1] * base + s[i];
for (int i = n; i >= 1; i--)
h2[i] = h2[i + 1] * base + r[i];
int maxl = 1;
for (int len = 2; len <= n; len++)
{
if (len % 2)
{
int l = len / 2;
if (get_hash1(n - l + 1, n) == get_hash2(n - 2 * l, n - l - 1))
maxl = len;
}
else
{
int l = len / 2;
if (get_hash1(n - l + 1, n) == get_hash2(n - 2 * l + 1, n - l))
maxl = len;
}
}
for (int i = 1; i <= n; i++)
cout << s[i];
for (int i = n - maxl; i >= 1; i--)
cout << s[i];
return 0;
}
G.
连通块间处理不会。弃了。

浙公网安备 33010602011771号