A - Doors in the Center
问题陈述
找出满足以下所有条件的长度为 \(N\) 的字符串:
- 每个字符都是
-
或=
。 - 它是一个回文字符串。
- 正好包含一个或两个
=
。如果包含两个=
,它们是相邻的。
这样的字符串是唯一的。
解题思路
简单构造题,把 '=' 构造到中间即可,偶数时放两个,奇数时放一个。
AC代码
#include<bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';
#define il inlineusing namespace std;
using ll = long long;
using ull = unsigned long long;int n;int main(){// freopen("test.in","r",stdin);// freopen("test.out","w",stdout);ios::sync_with_stdio(0),cout.tie(0),cin.tie(0);cin>>n;if(n&1){for(int i = 1;i <= n/2;i++)cout<<'-';cout<<'=';for(int i = 1;i <= n/2;i++)cout<<'-';}else{for(int i = 1;i <= n/2-1;i++)cout<<'-';cout<<"==";for(int i = 1;i <= n/2-1;i++)cout<<'-';}return 0;
}
B - Full House 3
问题陈述
我们有七张牌。 \(i\) -th 牌 \((i=1,\ldots,7)\) 上面写着一个整数 \(A_i\) 。
请判断是否有可能从这七张牌中选择五张,使所选的牌组成葫芦。
当且仅当满足以下条件时,一组五张牌被称为葫芦:
- 对于不同的整数 \(x\) 和 \(y\) ,有三张 \(x\) 和两张 \(y\) 。
解题思路
开桶暴力统计即可,一定要先找\(\geq 3\)的,不然会被重复数。
AC代码
#include<bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';
#define il inlineusing namespace std;
using ll = long long;
using ull = unsigned long long;int a[8],cnt[15];bool flag3 , flag2;int main(){// freopen("test.in","r",stdin);// freopen("test.out","w",stdout);ios::sync_with_stdio(0),cout.tie(0),cin.tie(0);for(int i = 1;i <= 7;i++)cin>>a[i];for(int i = 1;i <= 7;i++)cnt[a[i]]++;bool flag = 0;for(int i = 1;i <= 14;i++){if(cnt[i] >= 3){for (int j = 1; j <= 14; j++) {if (i != j && cnt[j] >= 2) {flag = true;break;}}if(flag)break;}}if(flag){cout<<"Yes";}else{cout<<"No";}return 0;
}
C - Uniqueness
问题陈述
有 \(N\) 个人,标记为 \(1\) 至 \(N\) 。人 \(i\) 有一个整数 \(A_i\) 。
在满足 "其他 \(N-1\) 人中没有一个人的整数与自己相同 "条件的人中,找出整数最大的那个人,并打印这个人的标签。
如果没有人满足条件,则报告这一事实。
解题思路
开个结构体然后用\(map\)暴力统计,把计数为\(1\)的元素放到新数组,找到新数组中的最大值,输出原下标即可。
AC代码
#include<bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';
#define il inline
#define inf 0x3f3f3f3fusing namespace std;
using ll = long long;
using ull = unsigned long long;const int maxn = 3e5+10;int n;
int a1[maxn];
int cnt;map<int,int> mp;struct node{int id,v;
}a[maxn];int main(){// freopen("test.in","r",stdin);// freopen("test.out","w",stdout);ios::sync_with_stdio(0),cout.tie(0),cin.tie(0);cin>>n;for(int i = 1;i <= n;i++){cin>>a1[i];mp[a1[i]]++;}for(int i = 1;i <= n;i++){if(mp[a1[i]] == 1){a[++cnt] = {i,a1[i]};}}int ans = -inf;int res;for(int i = 1;i <= cnt;i++){if(a[i].v > ans){ans = a[i].v;res = a[i].id;}}if(ans == -inf){cout<<-1;return 0;}cout<<res;return 0;
}
D - Bonfire
问题陈述
有一个无限大的二维网格,在坐标 \((0,0)\) 处有一堆篝火。
在时间 \(t=0\) ,只有单元格 \((0,0)\) 存在烟雾。
给你一个长度为 \(N\) 的字符串 \(S\) ,由 "N"、"W"、"S"、"E "组成。在 \(t=1,2,\dots,N\) 时刻,会依次发生以下情况:
- 风吹起,当时存在的所有烟雾按如下方式移动:
- 如果 \(S\) 的 \(t\) -th 字符是 "N", \((r,c)\) 单元格中的烟雾会移动到 \((r-1,c)\) 单元格。
- 如果是 "W", \((r,c)\) 单元格中的烟雾会移动到 \((r,c-1)\) 单元格。
- 如果是 "S", \((r,c)\) 单元格中的烟雾会移动到 \((r+1,c)\) 单元格。
- 如果是 "E", \((r,c)\) 单元格中的烟雾会移动到 \((r,c+1)\) 单元格。
- 如果单元格 \((0,0)\) 中没有烟雾,则会在单元格 \((0,0)\) 中产生新的烟雾。
高桥站在 \((R,C)\) 单元格。
对于每个整数 \(1 \le t \le N\) ,判断在时间 \(t+0.5\) 时,单元格 \((R,C)\) 是否存在烟雾,并按照要求的格式打印响应。
解题思路
对于每次更改当成更改原点,用\(unordered_set\)统计即可。
AC代码
#include<bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';
#define il inlineusing namespace std;
using ll = long long;
using ull = unsigned long long;ll n,r,c,dx,dy;
string s;
unordered_set<ll> vis;il ll hs(ll x,ll y){return x << 32 | (y & 0xffffffffll);}int main(){// freopen("test.in","r",stdin);// freopen("test.out","w",stdout);ios::sync_with_stdio(0),cout.tie(0),cin.tie(0);cin>>n>>r>>c>>s;vis.insert(hs(0, 0));string res;for (char a : s) {switch (a) {case 'N': {dx--; break;}case 'S': {dx++; break;}case 'W': {dy--; break;}case 'E': {dy++; break;}}ll key = hs(dx - r, dy - c);res += vis.count(key) ? '1' : '0';vis.insert(hs(dx, dy));}cout << res;return 0;
}
E - Tree Game
问题陈述
这个问题是一个交互式问题(在这个问题中,你的程序和法官系统通过输入和输出进行交流)。
给你一棵树 \(G\) ,其中有 \(N\) 个顶点,编号为 \(1\) 至 \(N\) 。 \(i\) 这条边连接着顶点 \(U_i\) 和 \(V_i\) 。
你们将用这棵树 \(G\) 与高桥玩一个游戏。首先,你们决定谁是第一名,谁是第二名。然后,从第一位玩家开始,轮流进行以下操作:
- 选择一对满足以下两个条件的整数 \((i,j)\) 和 \(1 \leq i < j \leq N\) ,然后添加一条连接顶点 \(i\) 和 \(j\) 到 \(G\) 的边。
- \(G\) 中没有连接顶点 \(i\) 和 \(j\) 的边。
- 添加一条连接顶点 \(i\) 和 \(j\) 的边不会产生奇循环。
无法进行此操作的棋手输棋,而另一方棋手赢棋。请与高桥先生下这盘棋并获胜。
什么是奇数循环?
当且仅当满足以下所有条件时, \(G\) 的顶点 \((v_0,v_1,\ldots,v_k)\) 序列称为奇数循环:
- \(k\) 是奇数。
- \(v_0=v_k\) .
- 对于每一个 \(1\leq i \leq k\) ,都有一条边连接 \(v_{i-1}\) 和 \(v_{i}\) 。
解题思路
二分图染色后模拟。
AC代码
#include<bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';
#define il inlineusing namespace std;
using ll = long long;
using ull = unsigned long long;const int maxn = 105;
const int maxm = 2e4+10;int color[maxn];
set<pair<int, int>> e,e2,e3;
bool flag;
int k,i,j;struct E {int to, next;
} Edge[maxm];int tot, Head[maxn];inline void add(int u, int v) {Edge[tot].to = v;Edge[tot].next = Head[u];Head[u] = tot++;
}void dfs(int u, int c) {color[u] = c;for (int i = Head[u];~i;i = Edge[i].next) {int v = Edge[i].to;if (color[v] == -1) {dfs(v, 1 - c);}}
}il void solve()
{if (flag) {while(1){if (e3.empty()) break;auto it = e3.begin();pair<int, int> ee = *it;cout << ee.first << " " << ee.second << endl;e3.erase(it);cin >> i >> j;if (i == -1 && j == -1) return;if (i > j) swap(i, j);e3.erase({i, j});}} else {while (1) {cin >> i >> j;if (i == -1 && j == -1) return;if (i > j) swap(i, j);e3.erase({i, j});if (e3.empty()) break;auto it = e3.begin();cout << it->first << " " << it->second << endl;e3.erase(it);}}
}int main() {// freopen("test.in","r",stdin);// freopen("test.out","w",stdout);// ios::sync_with_stdio(0),cout.tie(0),cin.tie(0);int n;cin >> n;memset(Head,-1, sizeof(Head));memset(color,-1, sizeof(color));for (int i = 0; i < n - 1; ++i) {int u, v;cin>>u>>v;add(u, v);add(v, u);if(u > v) swap(u, v);e.insert({u, v});}dfs(1, 0);for (int i = 1; i <= n; ++i) {for (int j = i + 1; j <= n; ++j) {if (color[i] != color[j]) {auto edge = (i < j) ? make_pair(i, j) : make_pair(j, i);if (e.find(edge) == e.end())e2.insert(edge);}}}k = e2.size();flag = 0;if (k == 0) {cout<<"Second"<<endl;return 0;} else {if (k & 1) {cout<<"First"<<endl;flag = 1;} else {cout<<"Second"<<endl;}}e3 = e2;solve();return 0;
}
F - ABCBA
问题陈述
找出一个以 \(S\) 为前缀的最短回文。
解题思路
KMP的拓展应用题,用Manacher也能当板子做,找最小循环节就好。
AC代码
#include<bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';
#define il inlineusing namespace std;
using ll = long long;
using ull = unsigned long long;int main(){// freopen("test.in","r",stdin);// freopen("test.out","w",stdout);ios::sync_with_stdio(0),cout.tie(0),cin.tie(0);string s;cin>>s;int n = s.size();string sr(s.rbegin(), s.rend());string s2 = sr + '#' + s;int m = s2.size();vector<int> p(m, 0);for (int i = 1; i < m; ++i) {int j = p[i-1];while (j > 0 && s2[i] != s2[j])j = p[j-1];if (s2[i] == s2[j])j++;p[i] = j;}int k = p.back();string add = s.substr(0, n - k);reverse(add.begin(), add.end());string ans = s + add;cout<<ans;return 0;
}