Codeforces 972 div2
A - Simple Palindrome
1、先对字母进行分配,每个字母分到 n / 5个
2、对剩余字母进行分配,前n % 5 个字母每一个分配一个
3、分别将其输出,相同字母放在一起,如果相同字母分开,就会出现如“ABA”这样的回文子串。
AC代码:
#include<bits/stdc++.h> using namespace std; char ss[7] = {' ','a','e','i','o','u'}; int n; void solve(){ cin >> n; int num1 = n / 5; int num2 = n % 5; int num[7]; memset(num, 0, sizeof num); for(int i = 1; i <= 5; ++i){ num[i] = num1; } for(int i = 1; i <= num2; ++i){ num[i]++; } for(int i = 1; i <= 5; ++i){ for(int j = 1; j <= num[i]; ++j){ cout<<ss[i]; } } cout << endl; return; } int main(){ ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int _; cin >> _; while(_--){ solve(); } return 0; }
B1 - The Strict Teacher (Easy Version)
1、因为只有两个老师,所以分两种情况判断
<1>学生在老师中间 ans = (两老师之间的距离) / 2;
<2>学生在墙和老师中间 ans = 老师距离墙的距离
AC代码:
#include<bits/stdc++.h> using namespace std; int n, m, q; int m1, m2, q1; void solve(){ cin >> n >> m >> q; cin >> m1 >> m2; cin >> q1; if((m1 < q1 && q1 < m2) || (m1 > q1 && q1 > m2)){ cout << labs(m1 - m2) / 2; }else if( q1 > m1 && q1 > m2){ cout<< (n - max(m1, m2)); }else if(q1 < m2 && q1 < m1){ cout<< min(m1, m2) - 1; } cout << endl; return; } int main(){ ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int _; cin >> _; while(_--){ solve(); } return 0; }
B2 - The Strict Teacher (Hard Version)
1、二分查找在学生之前的第一个老师和在学生之后的老师第一个老师
2、分类判断就行了
#include <bits/stdc++.h> using namespace std; const int N = 1e5+10; int n, m, q; int a[N], num; void solve() { cin >> n >> m >> q; for (int i = 0; i < m; ++i) { cin >> a[i]; } sort(a, a + m); for (int i = 1; i <= q; ++i) { cin >> num; // 找到第一个大于 num 的数 int greaterIdx = upper_bound(a, a + m, num) - a; // 找到第一个大于等于 num 的数,也就是可以用 lower_bound - 1 来得到小于 num 的数 int smallerIdx = lower_bound(a, a + m, num) - a - 1; // 输出结果 if (smallerIdx < 0) { // 如果不存在小于 num 的数 cout << a[greaterIdx] - 1; } else if (greaterIdx >= m) { // 如果不存在大于 num 的数 cout << n - a[smallerIdx]; }else { cout<<(a[greaterIdx] - a[smallerIdx]) / 2; } cout<<endl; } return; } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int _; cin >> _; while (_--) { solve(); } return 0; }
C - Lazy Narek
动态规划
每次更新以某个字母为结尾的最大得分
初始化:
- 设定一个
dp
数组来存储以“narek”中的各个字母结尾时的最大分数,初始值为极小值,只有dp[0]
(以'n'结尾)初始化为0。
动态规划过程:
- 对每个字符串 s[i],通过以下步骤更新dp数组:
- 储存上一轮的结果到
ndp
。 - 遍历“narek”的每个字母,通过
lower_bound
查找每个字符在s[i]
中出现的情况。 - 如果当前字符是所需字母且符合顺序,则增加分数;否则减少分数。
- 储存上一轮的结果到
更新分数:
- 更新
ndp[next]
,记录以下一个字母为结尾时的最大分数。 - 将
dp
更新为ndp
,为下一轮计算做准备。
结果计算:
- 最终结果
ans
初始化为0,遍历dp
数组,计算得分并考虑到未选择字符对对手得分的影响,得到最大值。
AC代码:
#include<bits/stdc++.h> using namespace std; const string narek = "narek"; int main(){ ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while(t--){ int n, m; cin >> n >>m; vector<string> s(n); for(int i = 0; i < n; ++i) cin >> s[i]; //dp数组存储的是当前以narek中任一字母结尾能达到的最大分数 //首先初始化初始分数为最小值 vector<int> dp(5, int(-1e9)), ndp; dp[0] = 0; for(int i = 0; i < n; ++i){ //储存上一轮结束时的结果 ndp = dp; //遍历每一个字母 for(int j = 0; j < 5; ++j){ //如果当前字母没有前驱 //例:以a开头,是非法的,跳过 if(dp[j] == int(-1e9))continue; //初始化当前分数为零, 我们下一个要找的字母为j int counted_score = 0, next = j; //遍历当前字符串 for(int k = 0; k < m; ++k){ //找当前字符有没有 narek中出现 int ind = narek.find(s[i][k]); //没找到,跳过当前循环 查找 下一个字符 if(ind == -1) continue; //如果下一个字母是我们需要的 if(next == ind){ next = (next + 1) % 5; //我们的分数加一 counted_score++; }else{ //否则我们的分数减一 counted_score--; } } //更新以next结尾的最大分数 ndp[next] = max(ndp[next], dp[j] + counted_score); } //更新dp数组 dp = ndp; } //因为什么都不选的结果为零,但是选了可能导致分数为负数 //因此初始化ans的值为0 int ans = 0; for(int i = 0; i < 5; ++i){ //减 2 * i的原因是,如果不以最后一个字符结尾,我们的分不加,对手的分数增加 //因此我们的分数需减去两倍 ans = max(ans, dp[i] - 2 * i); } cout << ans <<endl; } return 0; }
本文作者:lyx9785
本文链接:https://www.cnblogs.com/lyx9785/p/18415127
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步