连续两天的cf,哈哈哈。当时做了两题,还没补题。
比赛链接:Educational Codeforces Round 57 (Rated for Div. 2)
A
中文题意
输入一个l, r,表示闭区间[l, r]要求你输出一对x, y,使得x y都在这个区间,并且x整除y。如果有多组解,输出任意一种即可。
题解
我开场的时候好蠢啊,还想枚举,先是Wrong answer然后Time limit exceeded。最后突然发现,每次输出l 和 l * 2就可以了啊,题目保证了给的区间[l, r]是有解的。所以最小的解肯定是l和2 * l,并且2 * l <= r(题目保证的)
代码
#include<stdio.h>
#include<stdlib.h>
#include <iostream>
#include <cmath>
#include <set>
using namespace std;
#define maxn 100007
#define M 998244353
signed main()
{
int t;
cin >> t;
while (t--){
int flag = 0;
long long int l, r;
cin >> l >> r;
cout << l << " " << l * 2 << endl;
}
return 0;
}
B
中文题意
输入n以及一个长度为n的字符串s,你可以去掉s中的任意区间的连续子序列,使得剩下的字母全都相同(全部去除也算一种)。求一共有多少种去除的方法,最后结果mod998244353
样例
image.png在第一个样例中,你可以去掉[1, 2](剩下”aa“),去掉[1, 3](剩下”a“),去掉[1, 4](啥都不剩,也算一种),去掉[2, 2](剩下"aaa"),去掉2,3,去掉[2, 4](剩下"a")。所以答案是6种。
题解
我们很容易发现这道题最后剩下的只能是开头的若干个元素和末尾的若干个相同的元素。
- 定义:首元素子串:从头开始连续的相同的字母组成的子串;尾元素子串:从尾部开始连续的相同的字母组成的子串
首元素子串的长度为cnt1,尾元素子串长度为cnt2 - 如果首元素和尾元素不相同,那么每次去除都只能留下首元素子串或者尾元素子串,然后只留下首元素子串时有cnt1种分割方法,比如首元素子串为aaaa,那么可以留下[1, 1], [1, 2], [1, 3], [1, 4]。尾部元素同理有cnt2种分割方法,再加上一整个字符串都去掉的情况,就一共有cnt1 + cnt2 + 1种方法。
- 如果首元素也尾元素相同,那首元素子串的cnt1 + 1个分割点都可以对应尾元素子串的cnt2 + 1个分割点,所以就有(cnt1 + 1) * (cnt2 + 1)种分割方法。
代码
#include <iostream>
#include <cstring>
using namespace std;
int main(){
long long n;
string s;
while (cin >> n){
long long cnt1 = 0, cnt2 = 0;
cin >> s;
char tail = s[(int)s.size() - 1]; // 尾元素
char head = s[0]; // 首元素
//获取首元素子串的长度
for (long long i = (int)s.size() - 1; i >= 0; i--){
if (s[i] != tail){
break;
}
cnt1++;
}
// 获取尾元素子串的长度
for (long long i = 0; i < (int)s.size(); i++){
if (s[i] != head){
break;
}
cnt2++;
}
//其实这种情况不会发生,题面说了至少有两个字母不相同,是我多虑了
if (cnt1 == n){
cout << ((1 + n) * n / 2) % 998244353 << endl;
}
else{
//首尾不同
if (head != tail){
cout << (cnt1 + cnt2 + 1) % 998244353 << endl;
}
//首尾相同
else{
cout << ((cnt1 + 1) * (cnt2 + 1 )) % 998244353 << endl;
}
}
}
}
网友评论