Codeforces Round #674 (Div. 3)
比赛链接:https://codeforces.com/contest/1426
A. Floor Number
题意
一所房子除第一层有 $2$ 个房间外其余层有 $x$ 个房间,给出房间号 $n$,问该房间在第几层。
题解
既然除了第一层外每层房间数都相等,那么只需计算在第一层的基础上还需加上几层即可,即 $1 + \lceil \frac{n-2}{x} \rceil$ 。
代码
#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, x; cin >> n >> x; cout << 1 + (max(0, n - 2) + x - 1) / x << "\n"; } return 0; }
B. Symmetric Matrix
题意
给出 $n$ 个 $2 \times 2$ 的小正方矩阵和大正方矩阵的边长 $m$,小矩阵每个位置有一个数,每个小矩阵使用次数不限,问能否用小矩阵完全填补大矩阵且大矩阵关于主对角线对称。
题解
只要至少有一个小矩阵关于主对角线对称即可,其次为了完全填补,大矩阵的边长需要为 $2$ 的倍数。
代码
#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, m; cin >> n >> m; bool ok = false; for (int i = 0; i < n; i++) { int a, b, c, d; cin >> a >> b >> c >> d; if (b == c) ok = true; } cout << (ok and m % 2 == 0 ? "YES" : "NO") << "\n"; } return 0; }
C. Increase and Copy
题意
一开始数组中只有一个值为 $1$ 的数,每次操作可以选择:
- 给一个数加一
- 在末尾添加一个已有的数
问使得所有数之和为 $n$ 的最少操作次数。
题解
$n = a \times b + c$,枚举 $a$ 即可。
代码
#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; int ans = INT_MAX; for (int i = 1; i * i <= n; i++) { ans = min(ans, (i - 1) + (n / i - 1) + (n % i != 0)); } cout << ans << "\n"; } return 0; }
D. Non-zero Segments
题意
计算使一个数组没有和为 $0$ 的连续区间至少要插入多少个数。
题解
计算前缀和,如果当前和在之前出现过,那么说明之前有一段和为 $0$ 的区间,插入一个数后清空之前的记录从当前数重新计算即可。
代码
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; int ans = 0; set<long long> st; st.insert(0); long long sum = 0; for (int i = 0; i < n; i++) { int x; cin >> x; sum += x; if (st.count(sum)) { ++ans; st.clear(); st.insert(0); st.insert(sum = x); } else { st.insert(sum); } } cout << ans << "\n"; return 0; }
E. Rock, Paper, Scissors
题意
给出 $Alice$ 和 $Bob$ 各会出石头剪刀布的次数,问 $Alice$ 至少和至多会赢多少次。
题解
最多赢多少次比较好想,即 $min(a_1,b_2) + min(a_2,b_3) + min(a_3,b_1) $ 。
最少赢多少次应考虑那些不得不赢的情况,即减去输掉和平局的所有局数后还有余的次数,可以证明这种情况最多只有一种。
证明
如果存在两个 $a_i - b_i - b_{i+2} > 0$,比如 $a_1 > b_1 + b_3$,$a_2 > b_2 + b_1$,那么 $a_1 + a_2 > b_1 + b_2 + b_3 + b_1 = n + b_1$,即 $a_1 + a_2 > n$,与 $a_1 + a_2 + a_3 = n$ 矛盾,所以不得不赢的情况至多只存在一种。
代码
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vector<int> a(3), b(3); for (auto &x : a) cin >> x; for (auto &x : b) cin >> x; int ans1 = 0, ans2 = 0; for (int i = 0; i < 3; i++) { ans1 = max(ans1, a[i] - b[(i + 2) % 3] - b[i]); } for (int i = 0; i < 3; i++) { ans2 += min(a[i], b[(i + 1) % 3]); } cout << ans1 << ' ' << ans2 << "\n"; return 0; }
F. Number of Subsequences
题意
一个字符串由 $a,b,c$ 和 $k$ 个 $?$ 组成,$?$ 可以被替换为 $a,b,c$,问在 $3^k$ 个可能的字符串中共有多少个 $abc$ 序列。
题解
$dp_0$——字符串的个数
$dp_1$——$a$序列的个数
$dp_2$——$ab$序列的个数
$dp_3$——$abc$序列的个数
代码
#include <bits/stdc++.h> using namespace std; constexpr int MOD = 1e9 + 7; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; string s; cin >> s; vector<long long> dp(4); dp[0] = 1; for (char c : s) { if (c == '?') { for (int i = 3; i > 0; i--) dp[i] = (dp[i] * 3 + dp[i - 1]) % MOD; dp[0] = dp[0] * 3 % MOD; } else { int i = c - 'a' + 1; (dp[i] += dp[i - 1]) %= MOD; } } cout << dp[3] << "\n"; return 0; }
参考博客
https://blog.csdn.net/tomjobs/article/details/108858505