A. Simple Palindrome
大意
从元音字母“aeiou” 中组成字符串使得该字符串的回文子串最少
思路
每种字母尽可能数量相同且连续
code
#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
int t,n;
string s;
int main ()
{
cin >> t;
s = "aaeiou";
while(t --)
{
cin >> n;
int tmp1 = n / 5;
int tmp2 = n % 5;
for(int i = 1;i <= 5;++ i)
{
for(int j = 1;j <= tmp1;++ j)
{
cout << s[i];
}
if(tmp2){
cout << s[i];
tmp2 --;
}
}
cout << "\n";
}
return 0;
}
B1. The Strict Teacher (Easy Version)
code
#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int N = 1e5 + 10;
int t,n,m,q,a[N],b[N];
int main ()
{
cin >> t;
while(t --)
{
cin >> n >> m >> q;
LL d,l,r,ans = 0;
for(int i = 1;i <= m;++ i)
{
cin >> a[i];
}
sort(a + 1,a + 1 + m);
cin >> d;
auto it = lower_bound(a + 1,a + 1 + m,d);
if(it != a + 1 + m){
if(*it == d){
cout << "0\n";
continue;
}
r = *it;
} else {
ans += n - d;
r = 0;
}
it = upper_bound(a + 1,a + 1 + m,d);
if(it != a + 1){
it --;
l = *it;
} else{
l = 0;
ans += d - 1;
}
if(l == 0)ans += r - d;
else if(r == 0)ans += d - l;
else ans = (r - l) >> 1;
cout << ans << "\n";
}
return 0;
}
B2. The Strict Teacher (Hard Version)
大意:
多个老师追学生,各个老师的位置不一样,老师一次可以往左或右走一步或者停下等待,学生也是。老师追,学生逃,求老师追到学生的步数。在 B1 中学生的初始位置只有一个,只需求出这个位置的步数。B2中有多个位置,把每个位置的步数求出就行了。
思路
对于老师来说,只需要学生左边第一个老师和右边第一个老师出动形成两面包夹芝士。
对于学生,尽可能逃跑,当出现左边一个右边一个老师时,跑到中间等着被抓即可。若一方没有老师则跑到一方尽头等待被捕获。
所以我们用二分找到离学生最近的左右老师就行
code
#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int N = 1e5 + 10;
int t,n,m,q,a[N],b[N];
int main ()
{
cin >> t;
while(t --)
{
cin >> n >> m >> q;
LL d,l,r,ans = 0;
for(int i = 1;i <= m;++ i)
{
cin >> a[i];
}
sort(a + 1,a + 1 + m);
while(q --)
{
cin >> d;
ans = 0;
auto it = lower_bound(a + 1,a + 1 + m,d);
if(it != a + 1 + m){
if(*it == d){
cout << "0\n";
continue;
}
r = *it;
}else {
ans += n - d;
r = 0;
}
it = upper_bound(a + 1,a + 1 + m,d);
if(it != a + 1){
it --;
l = *it;
} else{
l = 0;
ans += d - 1;
}
if(l == 0)ans += r - d;
else if(r == 0)ans += d - l;
else ans = (r - l) >> 1;
cout << ans << "\n";
}
}
return 0;
}
C. Lazy Narek
大意
从n个字符串中选出几个字符串出来,按照在这些字符串前后顺序依照“narek”先后出现顺序,每当完整出现一次“narek”主角得5分,未参与形成“narek”的字母每个给gpt加一分 最后求主角 - gpt 分数最大值
题解
用dp去写这题,我们会从这些字符串中选出几个出来,所以就存在把这些字符串拼接起来问题。就会出现单独一个字符串不能组成“narek”需要多个拼接的情况,我们就以该个字符串中最后属于“narek”的字母来表示dp方程
用二维数组dp[i][j] 表示前 i 个字符串,以 “narek” 中第j个字母结尾的值。
同时用val[i][j] 表示第 i 个串以对应的 j 字母结尾的得分。
pla[i][j] 表示第i个字符串的对应的第 j 字符开始最后枚举到了的个位置,用于后续拼接时知晓此时末尾是什么字母
code
#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int N = 1e3 + 10;
int t,n,m,ans;
int val[N][10],pla[N][10],dp[N][N];
string s = "nnarek";
void solve(string a,int b,int c)
{
int cnt = 0,p = c,sc = 0;
for(int i = 0;i < m;++ i)
{
if(a[i] == 'n' || a[i] == 'a' || a[i] == 'r' || a[i] == 'e' || a[i] == 'k')cnt ++;
if(a[i] == s[p])
{
++ p;
if(p == 6){
p = 1;
sc ++;
}
}
}
val[b][c] = sc * 5 - (cnt - sc * 5); // 这里会出现负数
pla[b][c] = p;
}
int main ()
{
cin >> t;
while(t --)
{
cin >> n >> m;
ans = 0;
for(int i = 0;i <= n + 5;++ i)
{
for(int j = 0;j < 10;++ j)
{
dp[i][j] = N * (-1);
}
}
// 这里初始化赋值为较小数
for(int i = 1;i <= n;++ i)
{
string tmp;
cin >> tmp;
for(int j = 1;j <= 5;++ j)
{
solve(tmp,i,j);
}
}
dp[0][1] = 0;
for(int i = 1;i <= n;++ i)
{
for(int j = 1;j <= 5;++ j)
{
dp[i][j] = max(dp[i - 1][j],dp[i][j]);
dp[i][pla[i][j]] = max(dp[i][pla[i][j]],dp[i - 1][j] + val[i][j]);
}
}
for(int i = 1;i <= 5;++ i)
{
ans = max(ans,dp[n][i]);
}
cout << ans << "\n";
}
return 0;
}