一万一参赛,赛时(VP)排名 136
A. Simple Palindrome
简单构造题。字母集是 5 ,相同字母间一定构成若干回文子串。
将相同字母排列在一起,则只有相同字母可以构成回文子串。
显然,优先添加较少的字母即可。
#include<bits/stdc++.h>
using namespace std;
int T, n;
char s[5] = {'a', 'e', 'i', 'o', 'u'};
int main() {
scanf("%d", &T);
while(T --) {
scanf("%d", &n);
int flag = 0;
int t = n / 5;
int res = n % 5;
for(int i = 0; i < 5; i ++) {
if(i < res) flag = 1;
else flag = 0;
for(int j = 1; j <= t + flag; j ++)
putchar(s[i]);
}
putchar('\n');
}
return 0;
}
B2. The Strict Teacher (Hard Version)
Easy Version 直接原代码提交即可。
简单模拟题。将猫和老鼠一起按位置排个序。
对于相邻猫之间的所有老鼠,他们的生存时间是相同的,都为相邻猫距离的一半(注意细节)。
注意讨论第一只猫前面的老鼠和最后一只猫后面的老鼠即可。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int T, n, m, q, ans[N];
struct Node {
int pos, id;
bool operator < (const Node &t) const {
return pos < t.pos;
}
}a[N * 2];
int main() {
scanf("%d", &T);
while(T --) {
scanf("%d%d%d", &n, &m, &q);
for(int i = 1; i <= m; i ++)
scanf("%d", &a[i].pos), a[i].id = 0;
for(int i = 1; i <= q; i ++)
scanf("%d", &a[i + m].pos), a[i + m].id = i;
sort(a + 1, a + m + q + 1);
vector<int> p;
int ls = 0;
for(int i = 1; i <= m + q; i ++) {
if(!a[i].id) {
for(int t = 0; t < p.size(); t ++) {
int j = p[t];
if(!ls) ans[a[j].id] = a[i].pos - 1;
else ans[a[j].id] = (a[i].pos - ls) / 2;
}
ls = a[i].pos;
p.clear();
}
else p.push_back(i);
}
for(int i = 0; i < p.size(); i ++) {
int j = p[i];
ans[a[j].id] = n - ls;
}
for(int i = 1; i <= q; i ++)
printf("%d\n", ans[i]);
}
return 0;
}
C - Lazy Narek
各字串按顺序拼接,可取可不取,求最大可能权值。用 dp 维护即可。
具体的,f[i][j],表示考虑了前 i 个子串,当前结尾字母为第 j 个字母的最大权值。
答案为 max(f[n][j] - j) 。
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int T, n, m, f[N][5];
char s[N], S[5] = {'n', 'a', 'r', 'e', 'k'};
int main() {
scanf("%d", &T);
while(T --) {
scanf("%d%d", &n, &m);
f[0][0] = 0;
for(int j = 1; j < 5; j ++)
f[0][j] = -1e9;
for(int i = 1; i <= n; i ++) {
scanf("%s", s);
for(int j = 0; j < 5; j ++)
f[i][j] = f[i - 1][j];
for(int j = 0; j < 5; j ++) {
int t = j, res = 0;
for(int k = 0; k < m; k ++) {
if(s[k] == S[t]) {
t = (t + 1) % 5;
if(!t) res += 5;
}
else {
for(int p = 0; p < 5; p ++)
if(s[k] == S[p]) res --;
}
}
f[i][t] = max(f[i][t], f[i - 1][j] + res);
}
}
int ans = 0;
for(int i = 0; i < 5; i ++)
ans = max(ans, f[n][i] - i);
printf("%d\n", ans);
}
return 0;
}
E1. Subtangle Game (Easy Version)
数据范围 n,m,l 均为 300 ,全局状态数仅为 n3 ,记搜即可。
具体的,f[i][j][k] 表示当前选到序列第 i 个数,在表格的 (j,k) 位置,最后是谁赢。
最后答案显然是 f[1][0][0] 。
#include<bits/stdc++.h>
using namespace std;
const int N = 305;
int T, l, n, m, a[N], s[N][N];
int f[N][N][N];
bool dfs(int cur, int r, int c) {
if(cur == l + 1) { f[cur][r][c] = !(cur & 1); return !(cur & 1); }
if(r == n || c == m) { f[cur][r][c] = !(cur & 1); return !(cur & 1); }
if(f[cur][r][c] != -1) return f[cur][r][c];
for(int i = r + 1; i <= n; i ++)
for(int j = c + 1; j <= m; j ++) {
if(s[i][j] == a[cur]) {
bool flag = dfs(cur + 1, i, j);
if(flag == (cur & 1)) {
f[cur][r][c] = (cur & 1);
return (cur & 1);
}
}
}
f[cur][r][c] = !(cur & 1);
return !(cur & 1);
}
int main() {
scanf("%d", &T);
while(T --) {
scanf("%d%d%d", &l, &n, &m);
for(int i = 1; i <= l; i ++)
scanf("%d", &a[i]);
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
scanf("%d", &s[i][j]);
for(int i = 0; i <= l; i ++)
for(int j = 0; j <= n; j ++)
for(int k = 0; k <= m; k ++)
f[i][j][k] = -1;
bool ans = dfs(1, 0, 0);
puts(ans ? "T" : "N");
}
return 0;
}