AtCoder Beginner Contest 298
A - Job Interview (abc298 a)
题目大意
给定包含o-x
的字符串,问是否不包含 x
且包含o
。
解题思路
遍历一遍即可。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n; string s; cin >> n >> s; auto ok = [&](){ if (s.find('x') != string::npos) return false; if (s.find('o') == string::npos) return false; return true; }; if (ok()) cout << "Yes" << '\n'; else cout << "No" << '\n'; return 0; }
B - Coloring Matrix (abc298 b)
题目大意
给定两个方阵,问能否将 旋转多次 度,使得 为 的地方也为 。
解题思路
大小只有,四次翻转都试一次就可以了,题意也给出了翻转的位置变换公式。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n; cin >> n; vector<vector<int>> a(n, vector<int>(n, 0)), b(n, vector<int>(n, 0)); for(auto &i : a) for(auto &j : i) cin >> j; for(auto &i : b) for(auto &j : i) cin >> j; auto check = [&](){ for(int i = 0; i < n; ++ i) for(int j = 0; j < n; ++ j){ if (a[i][j] == 1 && b[i][j] != 1) return false; } return true; }; auto ok = [&](){ vector<vector<int>> tmp(n, vector<int>(n, 0)); for(int i = 0; i < n; ++ i) for(int j = 0; j < n; ++ j){ tmp[i][j] = a[n - 1 - j][i]; } a = tmp; return check(); }; if (ok() || ok() || ok() || ok()) cout << "Yes" << '\n'; else cout << "No" << '\n'; return 0; }
C - Cards Query Problem (abc298 c)
题目大意
有个箱子,进行以下三种操作:
1 i j
将写有数字的卡片放到 号箱2 i
问号箱里放的所有卡片的数字,升序输出3 i
问写有数字的卡片所在的箱子编号,升序输出
解题思路
注意一个箱子里可能有多张一样数字的卡片,因此第二种操作用multiset
,第三种操作用set
维护即可。
神奇的代码
#include <bits/stdc++.h> #include <vector> using namespace std; using LL = long long; const int N = 2e5; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n, q; cin >> n >> q; vector<multiset<int>> box(n); vector<set<int>> card(N); while(q--){ int op; cin >> op; if (op == 1){ int i, j; cin >> i >> j; i --; j --; box[j].insert(i); card[i].insert(j); }else if (op == 2){ int i; cin >> i; -- i; for(auto &i : box[i]) cout << i + 1 << ' '; cout << '\n'; }else if (op == 3){ int i; cin >> i; -- i; for(auto &i : card[i]) cout << i + 1 << ' '; cout << '\n'; }else { assert(1 == 0); } } return 0; }
D - Writing a Numeral (abc298 d)
题目大意
一个字符串,初始值为1
。维护以下三种操作:
1 x
末尾增加个数字2
剔除的第一个数字3
问所表示的数字对 的取模
解题思路
事先维护下的幂对 的取模结果,然后动态维护这个取模值就可以了。
即操作1相当于 ,操作2相当于
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; const int N = 6e5 + 10; const int mo = 998244353; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); vector<int> mod(N); int mul = 1; for(int i = 1; i < N; ++ i){ mod[i] = mul; mul = 1ll * mul * 10 % mo; } deque<int> s; s.push_back(1); int q; cin >> q; int ans = 1; while(q--){ int op; cin >> op; if (op == 1){ int x; cin >> x; s.push_back(x); ans = (1ll * ans * 10 + x) % mo; }else if (op == 2){ int x = s.front(); ans = (ans - 1ll * x * mod[s.size()]) % mo; if (ans < 0) ans += mo; s.pop_front(); }else if (op == 3){ cout << ans << '\n'; }else { assert(1 == 0); } } return 0; }
E - Unfair Sugoroku (abc298 e)
题目大意
一维数轴,高桥在号点, 青木在 号点,高桥先,两人轮流扔骰子,高桥的结果会在 等概率出现,青木的在 等概率出现,掷出 后,就会往前走 步,最多到号点。谁先到号点谁赢。
问高桥赢的概率。
解题思路
设表示高桥在 号点,青木在号点,现在轮到高桥/青木时,高桥赢的概率。
然后根据扔骰子的情况和概率转移即可。
比如,注意可能要和 取个
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; const int mo = 998244353; long long qpower(long long a, long long b){ long long qwq = 1; while(b){ if (b & 1) qwq = qwq * a % mo; a = a * a % mo; b >>= 1; } return qwq; } long long inv(long long x){ return qpower(x, mo - 2); } int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n, a, b, p, q; cin >> n >> a >> b >> p >> q; int invp = inv(p); int invq = inv(q); vector<vector<vector<int>>> dp(n + 1, vector<vector<int>>(n + 1, vector<int>(2, -1))); function<int(int, int, int)> dfs = [&](int x, int y, int pos){ if (x == n) return 1; else if (y == n) return 0; if (dp[x][y][pos] != -1) return dp[x][y][pos]; int val = 0; if (pos == 0){ for(int i = 1; i <= p; ++ i){ int nx = min(n, x + i); val += dfs(nx, y, pos ^ 1); if (val >= mo) val -= mo; } val = 1ll * val * invp % mo; }else{ for(int i = 1; i <= q; ++ i){ int ny = min(n, y + i); val += dfs(x, ny, pos ^ 1); if (val >= mo) val -= mo; } val = 1ll * val * invq % mo; } return dp[x][y][pos] = val; }; cout << dfs(a, b, 0) << '\n'; return 0; }
F - Rook Score (abc298 f)
题目大意
给定一个大小的网格,以及 个格子上写的正数。
指定一个格子位置,问 行格子和 列格子的所有数的和。
解题思路
设 表示第 行的和, 表示第 列的和。
首先考虑选的有正数的情况,这个枚举一下取个最大值即可,即
然后还剩下一种就是 上没有数的情况。这个情况相当于从和 两个数组选一个数,求最大值,且 没数的。
一开始就是考虑用堆,就是两个数组选两个数求第 大的 的做法,直到找到一个没有数的位置就直接 ,理论上最多也就判断个 次就会 的,复杂度应该是 ,但是一直超时,感觉不太懂。
然后改成直接循环的,遇到第一个格子上没有数值的直接 ,这样最多也就遍历到 个点,复杂度是 。
多个 不至于吧。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n; cin >> n; map<int, LL> csum, rsum; set<pair<int, int>> po; set<pair<pair<int, int>, int>> po2; for(int i = 1; i <= n; ++ i){ int x, y, v; cin >> x >> y >> v; csum[y] += v; rsum[x] += v; po.insert({x, y}); po2.insert({{x, y}, v}); } LL ans = 0; for(auto &[pos, v] : po2){ auto &[x, y] = pos; ans = max(ans, rsum[x] + csum[y] - v); } vector<pair<int, LL>> COLSUM, ROWSUM; ROWSUM.reserve(rsum.size()); COLSUM.reserve(csum.size()); for(auto &i : rsum){ ROWSUM.push_back({i.first, i.second}); } for(auto &i : csum){ COLSUM.push_back({i.first, i.second}); } vector<int> col_id(COLSUM.size()), row_id(ROWSUM.size()); iota(row_id.begin(), row_id.end(), 0); iota(col_id.begin(), col_id.end(), 0); sort(row_id.begin(), row_id.end(), [&](const int a, const int b){ return ROWSUM[a].second > ROWSUM[b].second; }); sort(col_id.begin(), col_id.end(), [&](const int a, const int b){ return COLSUM[a].second > COLSUM[b].second; }); for(auto &r : row_id) for(auto &c: col_id){ int x = ROWSUM[r].first, y = COLSUM[c].first; if (po.find({x, y}) == po.end()){ ans = max(ans, ROWSUM[r].second + COLSUM[c].second); break; } } // ans = max({ans, COLSUM[col_id[0]].second, ROWSUM[row_id[0]].second}); // priority_queue<pair<LL, pair<int, int>>> qwq; // qwq.push({COLSUM[col_id[0]].second + ROWSUM[row_id[0]].second, {0, 0}}); // while(!qwq.empty()){ // auto [val, pos] = qwq.top(); // auto &[x, y] = pos; // qwq.pop(); // int real_row = ROWSUM[row_id[x]].first; // int real_col = COLSUM[col_id[y]].first; // if (po.find({real_row, real_col}) == po.end()){ // ans = max(ans, val); // break; // } // int nx = x + 1, ny = y + 1; // if (nx < row_id.size()){ // qwq.push({ROWSUM[row_id[nx]].second + COLSUM[col_id[y]].second, {nx, y}}); // } // if (ny < col_id.size()){ // qwq.push({ROWSUM[row_id[x]].second + COLSUM[col_id[ny]].second, {x, ny}}); // } // } cout << ans << '\n'; return 0; }
G - Strawberry War (abc298 g)
题目大意
给定一个的格子蛋糕,每个格子上有若干个草莓。
现在切 刀,每刀只能切到行交界处或列交界处,且长度为一格的长度。
问最后格子上草莓数量的最大值和最小值的差值的最小值。
解题思路
<++>
神奇的代码
Ex - Sum of Min of Length (abc298 h)
题目大意
<++>
解题思路
<++>
神奇的代码
本文作者:~Lanly~
本文链接:https://www.cnblogs.com/Lanly/p/17322258.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2020-04-15 Codeforces Round #633 (Div. 1)