A. Simple Palindrome
题意
让你构造一个长度为n的,只含5种字符的,回文子串最少的字符串
大概思路
同种字符内部配对,对回文子串总数的贡献与字符位置无关。但若出现“aba”这种相间的,则会产生额外贡献。根据自觉,不能让整个字符串字符全一样,得尽可能平均。
参考代码
void solve(){
int n;
cin >> n;
string s = "aeiou";
vector<int> a(5);
for (int i = 0; i < n; i++) {
a[i % 5]++;
}
for (int i = 0; i < 5; i++) {
while (a[i]--) cout << s[i];
}
cout << "\n";
}
B2. The Strict Teacher (Hard Version)
题意
n个格子,上面有m个老师,进行q次询问,每次要回答“若学生在x处,则老师抓到学生的最短时间是多少”,老师学生互相能看到行动,所以都会最优地移动。(老师学生同时移动,每次都只能移动一格,或者原地不动)
大概思路
贪心,分类讨论学生在最左边的老师的左边和最右边的老师的右边的情况,以及被两个老师夹住的情况就行
参考代码
void solve(){
int n, m, q;
cin >> n >> m >> q;
vector<int> p(m);
for (auto &i : p) cin >> i;
sort(p.begin(), p.end());
while (q--) {
int x;
cin >> x;
auto it = upper_bound(p.begin(), p.end(), x);
if (it == p.end()) {
cout << n - p.back() << "\n";
continue;
}
if (it == p.begin()) {
cout << p.front() - 1 << "\n";
continue ;
}
int i = it - p.begin();
cout << (p[i] - p[i - 1]) / 2 << "\n";
}
}
C. Lazy Narek
题意
给定n个长度为m的字符串,从中不改变顺序的情况下选任意的字符串拼接到一起,然后从左到右依次匹配 “n”, “a”, “r”, “e”, 和 “k”,循环匹配,要是遗漏了任何一个"narek"字符,GPT得1分,否则,每匹配成功一个"narek",玩家得一分。问玩家得分 $score_n$ 和 GPT得分 $score_c$ 的差值最大为多少
大概思路
一开始看错题了,写了个逆天4维dp
考虑dp转移,设dp[i][j]代表考虑到第i个字符串时,以5个字符的第j个字符结尾时的差值最大值。
设从字符结尾为第j个开始,若选了第i个字符串,最后的字符结尾为k,得分变化为S,那么转移方程如下:
$$ dp[i + 1][k] = max(dp[i + 1][k], dp[i][j] + S) $$
然后注意边界条件和一些转移的细节就行。
参考代码
std::string mt = "narek";
void solve(){
int n, m;
std::cin >> n >> m;
std::vector<std::string> a(n);
for (auto &s : a) std::cin >> s;
std::vector<std::array<i64, 5>> dp(n + 1);
auto wk = [&](int now, int i) -> std::pair<i64, i64> {
std::string& s = a[i];
int ans = 0;
for (int i = 0; i < m; i++) {
if (s[i] == mt[now]) {
now++;
if (now == 5) ans += 10, now = 0;
}
if (mt.find(s[i]) != -1) ans--;
}
return {now, ans};
};
for (int i = 0; i <= n; i++)for (int j = 0; j < 5; j++) {
dp[i][j] = -2e9;
}
dp[0][0] = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < 5; j++) {
dp[i + 1][j] = std::max(dp[i + 1][j], dp[i][j]);
auto [N, S] = wk(j, i);
dp[i + 1][N] = std::max(dp[i + 1][N], dp[i][j] + S);
}
}
i64 ans = 0;
for (int i = 0; i < 5; i++) ans = std::max(ans, dp[n][i]);
std::cout << ans << "\n";
}