目录
A
Problem/题意
给出连续 n * 7 天的步数,求每周有多少步。
Thought/思路
略
Code/代码
#include "bits/stdc++.h"
signed main() {
int n; std::cin >> n;
int sum = 0;
for (int i = 1; i <= 7 * n; ++ i) {
int x; std::cin >> x;
sum += x;
if (i % 7 == 0) {
std::cout << sum << " ";
sum = 0;
}
}
return 0;
}
B
Problem/题意
给出n个字符串,求两两组合之后,有没有回文串。
Thought/思路
数据很小,暴力
Code/代码
#include "bits/stdc++.h"
bool check(std::string s) {
bool res = true;
int len = s.length();
for (int i = 0; i < len / 2; ++ i) {
if (s[i] != s[len - i - 1]) {
res = false;
break;
}
}
return res;
}
signed main() {
int n; std::cin >> n;
std::vector <std::string > v(n + 1);
for (int i = 1; i <= n; ++ i) {
std::cin >> v[i];
}
bool flag = false;
for (int i = 1; i <= n; ++ i) {
for (int j = i + 1; j <= n; ++ j) {
std::string a = v[i] + v[j], b = v[j] + v[i];
if (check(a) or check(b)) {
flag = true;
}
}
}
if (flag) std::cout << "Yes";
else std::cout << "No";
}
C
Problem/题意
给出三个字符矩阵a、b、x,将a、b摆放到一个空白的矩阵上,求能否用x将a、b带来的所有黑格子覆盖。
Thought/思路
矩阵很小,首先能想到,假设在一个 20 * 20 的矩阵中,改变a、b的起始位置(本质上就是偏移量),然后检查x的每个点:
(1)对于a,是否在a的范围内,a提供在这个点的块,是不是黑色;
(2)对于b,是否在b的范围内,b提供在这个点的块,是不是黑色;
因为a、b还有可能存在位于x之外的黑色块,因此还要计算一下范围内的黑色快是否一致。
(这题真逆天)
Code/代码
#include "bits/stdc++.h"
std::array <int, 3> n, m, num;
std::array <std::vector <std::string>, 3> s;
signed main() {
for (int i = 0; i <= 2; ++ i) {
std::cin >> n[i] >> m[i];
s[i].resize(n[i]);
for (int j = 0; j < n[i]; ++ j) {
std::cin >> s[i][j];
num[i] += std::count(s[i][j].begin(), s[i][j].end(), '#');
}
}
auto check = [&](int ax, int ay, int bx, int by) { // 偏移量
int cnt = 0;
for (int i = 0; i < n[2]; ++ i) {
for (int j = 0; j < m[2]; ++ j) {
int target = (s[2][i][j] == '#');
int ta = (i >= ax and j >= ay and i < ax + n[0] and j < ay + m[0] and s[0][i - ax][j - ay] == '#');
int tb = (i >= bx and j >= by and i < bx + n[1] and j < by + m[1] and s[1][i - bx][j - by] == '#');
cnt += ta + tb;
if (target != (ta | tb)) {
return false;
}
}
}
return (cnt == num[0] + num[1]);
};
for (int ax = -10; ax <= 10; ++ ax)
for (int ay = -10; ay <= 10; ++ ay)
for (int bx = -10; bx <= 10; ++ bx)
for (int by = -10; by <= 10; ++ by)
if (check(ax, ay, bx, by))
{
std::cout << "Yes";
return 0;
}
std::cout << "No";
return 0;
}
D
Problem/题意
给一个包含 '(' 和 ')' 的字符串,可以将匹配括号内的内容全部删去,问最后的字符串长啥样。
Thought/思路
遇到 '(' 就存入栈,遇到 ')' 就标记,最后做个前缀和。
(这不比C题简单)
Code/代码
#include "bits/stdc++.h"
int l_stk[200007], pre[200007];
int l_top, n;
char s[200007];
signed main() {
std::cin >> n >> s + 1;
for (int i = 1; i <= n; ++ i) {
if (s[i] == '(') l_stk[++ l_top] = i;
if (s[i] == ')' and l_top > 0) {
pre[l_stk[l_top --]] ++;
pre[i + 1] --;
}
}
for (int i = 1; i <= n; ++ i) {
pre[i] = pre[i] + pre[i - 1];
}
for (int i = 1; i <= n; ++ i) {
if (pre[i] == 0) std::cout << s[i];
}
}
E
Problem/题意
有n个人排成一个环,有m个不同的数字[0, m - 1],问有多少种分配方案使得相邻两个人的数字不同。
Thought/思路
如果是线性的,那么第一个人是m种,往后都是m - 1种,则有种。
由于要求成环形,那么起到决定作用的就是最后一个数字。
而为了确定最后一个数字,我们需要确定倒数第二个数字的情况:
(1)如果第一个数字和倒数第二个数字相同,答案就是 ;
(2)如果第一个数字和倒数第二个数字不同,答案就是 ;
基于此,我们可以考虑用dp来解决这道题。
设表示前 i 个人中,第 1 个数字与第 i 个数字是否一致:
(1)若第1个数字和第i个数字相同,那么 ;
(2)若第1个数字和第i个数字不同,那么 ;
(3)若新加入了一个数字,且与第1个数字相同,那么 ;
最后输出 即可。
Code/代码
#include "bits/stdc++.h"
#define int long long
int n, m, dp[1000007][2]; // 0:dif 1:same
const int mod = 998244353;
signed main() {
std::cin >> n >> m;
dp[1][1] = m; // 一开始只有相同的情况,且为m种
for (int i = 1; i <= n - 1; ++ i) {
dp[i + 1][0] += dp[i][0] * (m - 2); // 从 1 与 i 不同的情况转移(所以是dp[i][0]),且与 1 和 i 都不同(所以是dp[i+1][0])
dp[i + 1][0] += dp[i][1] * (m - 1); // 从 1 与 i 相同的情况转移(所以是dp[i][1]),且与 1 和 i 都不同(所以是dp[i+1][0])
dp[i + 1][1] += dp[i][0] * 1;
dp[i + 1][0] %= mod;
dp[i + 1][1] %= mod;
}
std::cout << dp[n][0];
}