cf Educational Codeforces Round 106 E. Chaotic Merge

2024-03-24 07:32

本文主要是介绍cf Educational Codeforces Round 106 E. Chaotic Merge,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原题:
E. Chaotic Merge
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

You are given two strings x and y, both consist only of lowercase Latin letters. Let |s| be the length of string s.

Let’s call a sequence a a merging sequence if it consists of exactly |x| zeros and exactly |y| ones in some order.

A merge z is produced from a sequence a by the following rules:

if ai=0, then remove a letter from the beginning of x and append it to the end of z;
if ai=1, then remove a letter from the beginning of y and append it to the end of z.

Two merging sequences a and b are different if there is some position i such that ai≠bi.

Let’s call a string z chaotic if for all i from 2 to |z| z i ≠ z i − 1 z_i ≠ z_{i-1} zi=zi1.

Let s[l,r] for some 1 ≤ l ≤ r ≤ ∣ s ∣ 1≤l≤r≤|s| 1lrs be a substring of consecutive letters of s, starting from position l and ending at position r inclusive.

Let f ( l 1 , r 1 , l 2 , r 2 ) f(l1,r1,l2,r2) f(l1,r1,l2,r2) be the number of different merging sequences of x [ l 1 , r 1 ] x[l1,r1] x[l1,r1] and y [ l 2 , r 2 ] y[l2,r2] y[l2,r2] that produce chaotic merges. Note that only non-empty substrings of x and y are considered.

Calculate ∑ f ( l 1 , r 1 , l 2 , r 2 ) \sum f(l1,r1,l2,r2) f(l1,r1,l2,r2),其中 1 ≤ l 1 ≤ r 1 ≤ ∣ x ∣ a n d 1 ≤ l 2 ≤ r 2 ≤ ∣ y ∣ 1≤l_1≤r_1≤|x| and 1≤l_2≤r_2≤|y| 1l1r1xand1l2r2y Output the answer modulo 998244353.
Input

The first line contains a string x(1≤|x|≤1000).

The second line contains a string y (1≤|y|≤1000).

Both strings consist only of lowercase Latin letters.
Output

Print a single integer — the sum of f(l1,r1,l2,r2) over 1≤l1≤r1≤|x| and 1≤l2≤r2≤|y| modulo 998244353

.
Examples
Input
Copy

aaa
bb

Output
Copy

24

Input
Copy

code
forces

Output
Copy

1574

Input
Copy

aaaaa
aaa

Output
Copy

0

Input
Copy

justamassivetesttocheck
howwellyouhandlemodulooperations

Output
Copy

667387032

Note

In the first example there are:
6
pairs of substrings “a” and “b”, each with valid merging sequences “01” and “10”;
3
pairs of substrings “a” and “bb”, each with a valid merging sequence “101”;
4
pairs of substrings “aa” and “b”, each with a valid merging sequence “010”;
2
pairs of substrings “aa” and “bb”, each with valid merging sequences “0101” and “1010”;
2
pairs of substrings “aaa” and “b”, each with no valid merging sequences;
1
pair of substrings “aaa” and “bb” with a valid merging sequence “01010”;

Thus, the answer is 6⋅2+3⋅1+4⋅1+2⋅2+2⋅0+1⋅1=24.

中文:
给你两个字符串,x和y。然后再给你一个由01组成的字符串z,根据字符串x和y以及01序列z可以拼成另一个字符串s,如果z[i]等于0那么从x开头拿一个字符串放到s,如果是1那么从y拿一个字符放到s。这里要求所有的s必须满足s[i] != s[i-1],现在问你
在字符串x中截取一段[x1,y1]在字符串y中截取[x2,y2]可以满足s[i] != s[j] 且所有s各不相同的z有多少种?

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1000 + 5;
const ll mod = 998244353;
char x[maxn], y[maxn];
ll dp[maxn][maxn][2];
ll px[maxn], py[maxn];int main()
{ios::sync_with_stdio(false);while(cin>>x + 1 >> y + 1){int ans = 0;int n = strlen(x+1);int m = strlen(y+1);memset(dp,0,sizeof(dp));memset(px,0,sizeof(px));memset(py,0,sizeof(py));for (int i=1;i<=n;i++){px[i] = 1;if (x[i - 1] != x[i]){px[i] += px[i-1];px[i] %= mod;}}for (int i=1;i<=m;i++){py[i] = 1;if (y[i - 1] != y[i]){py[i] += py[i-1];py[i] %= mod;}}for (int i=1;i<=n;i++){for (int j=1;j<=m;j++){if (x[i] != y[j]){dp[i][j][0] = (dp[i][j][0] + py[j]) % mod;dp[i][j][1] = (dp[i][j][1] + px[i]) % mod;dp[i][j][0] = (dp[i][j][0] + dp[i-1][j][1]) % mod;dp[i][j][1] = (dp[i][j][1] + dp[i][j-1][0]) % mod;//cout <<"i = " << i << " j = " << j << " dp[i][j][0] = " << dp[i][j][0] << std::endl;}if (x[i-1] != x[i]){dp[i][j][0] += dp[i-1][j][0];dp[i][j][0] %= mod;}if (y[j-1] != y[j]){dp[i][j][1] += dp[i][j-1][1];dp[i][j][1] %= mod;}ans = (ans + dp[i][j][0] + dp[i][j][1]) % mod;}}cout << ans << endl;}return 0;
}

思路:

组合计数问题,一看就是dp。
容易考虑到设置状态dp[i][j]表示取到x的第i个字符,取到y的第j个字符时有多少种01序列满足,但是题目中要求z[i]!=z[i-1],所以要增加一个状态用来标记最后一个字符是什么
设置dp[i][j][k] 其中k等于0或者1,当k为0表示最后一个字符是x的最后一个字符结尾,k为1表示最后一个字符是y的最后一个。

这里如果考虑dp[i][j][k]表示字符串x从第一个连续拿到第|x|个,字符串y从第一个连续拿到第|y|个有多少中构造01序列的方法,状态转移方程还是很容易得到的,但是现在题目中要求的是x与y的任意连续字串能构造出多少个满足条件的z,如何解决呢?

仍然可以使用上面上面的状态进行进行计数,那么上面的状态表示的是:
x取[a,i],y取[b,j],且最后一个字符是x结尾或者是y结尾时,能构成的01序列的个数,即取以i结尾x的字串,以j结尾y的字串构成01序列。

当x[i]!=x[i-1]是,有状态转移方程:
d p [ i ] [ j ] [ 0 ] + = d p [ i − 1 ] [ j ] [ 0 ] dp[i][j][0] += dp[i-1][j][0] dp[i][j][0]+=dp[i1][j][0] 表示以x串结尾,且x的第i个字符与x的第i-1个字符不相同的情况。
同理y[j]!=y[j-1]
d p [ i ] [ j ] [ 1 ] + = d p [ i ] [ j − 1 ] [ 1 ] dp[i][j][1] += dp[i][j-1][1] dp[i][j][1]+=dp[i][j1][1]

当x[i]!=y[j]时
d p [ i ] [ j ] [ 0 ] + = d p [ i − 1 ] [ j ] [ 1 ] dp[i][j][0] += dp[i-1][j][1] dp[i][j][0]+=dp[i1][j][1] 表示x的第i个字符加到y的第j个字符的后面
同理
d p [ i ] [ j ] [ 1 ] + = d p [ i ] [ j − 1 ] [ 0 ] dp[i][j][1] += dp[i][j-1][0] dp[i][j][1]+=dp[i][j1][0]

上面的累计计数是不完整的,还需考虑如下的两种情况:

  1. d p [ i ] [ j ] [ 0 ] + = p y [ j ] dp[i][j][0] += py[j] dp[i][j][0]+=py[j]
  2. d p [ i ] [ j ] [ 1 ] + = p x [ i ] dp[i][j][1] += px[i] dp[i][j][1]+=px[i]

其中py[j]表示以y[j]结尾,仅使用字符串y能构成y[j]!=y[j-1]的字符粗的数量,同理px[i]
那么,上面第一种情况补充的是字符串x仅使用第x[i]个字符加到py[j]的后面
同理第二种情况

最后累计全部中间的字符串数量即可

这篇关于cf Educational Codeforces Round 106 E. Chaotic Merge的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/840875

相关文章

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

cf 164 C 费用流

给你n个任务,k个机器,n个任务的起始时间,持续时间,完成任务的获利 每个机器可以完成任何一项任务,但是同一时刻只能完成一项任务,一旦某台机器在完成某项任务时,直到任务结束,这台机器都不能去做其他任务 最后问你当获利最大时,应该安排那些机器工作,即输出方案 具体建图方法: 新建源汇S T‘ 对任务按照起始时间s按升序排序 拆点: u 向 u'连一条边 容量为 1 费用为 -c,

Codeforces Round #261 (Div. 2)小记

A  XX注意最后输出满足条件,我也不知道为什么写的这么长。 #define X first#define Y secondvector<pair<int , int> > a ;int can(pair<int , int> c){return -1000 <= c.X && c.X <= 1000&& -1000 <= c.Y && c.Y <= 1000 ;}int m

Codeforces Beta Round #47 C凸包 (最终写法)

题意慢慢看。 typedef long long LL ;int cmp(double x){if(fabs(x) < 1e-8) return 0 ;return x > 0 ? 1 : -1 ;}struct point{double x , y ;point(){}point(double _x , double _y):x(_x) , y(_y){}point op

Codeforces Round #113 (Div. 2) B 判断多边形是否在凸包内

题目点击打开链接 凸多边形A, 多边形B, 判断B是否严格在A内。  注意AB有重点 。  将A,B上的点合在一起求凸包,如果凸包上的点是B的某个点,则B肯定不在A内。 或者说B上的某点在凸包的边上则也说明B不严格在A里面。 这个处理有个巧妙的方法,只需在求凸包的时候, <=  改成< 也就是说凸包一条边上的所有点都重复点都记录在凸包里面了。 另外不能去重点。 int

CF 508C

点击打开链接 import java.util.Arrays;import java.util.Scanner;public class Main {public static void main(String [] args){new Solve().run() ;} }class Solve{int bit[] = new int[608] ;int l

Codeforces 482B 线段树

求是否存在这样的n个数; m次操作,每次操作就是三个数 l ,r,val          a[l] & a[l+1] &......&a[r] = val 就是区间l---r上的与的值为val 。 也就是意味着区间[L , R] 每个数要执行 | val 操作  最后判断  a[l] & a[l+1] &......&a[r] 是否= val import ja

Codeforces Round 971 (Div. 4) (A~G1)

A、B题太简单,不做解释 C 对于 x y 两个方向,每一个方向至少需要 x / k 向上取整的步数,取最大值。 由于 x 方向先移动,假如 x 方向需要的步数多于 y 方向的步数,那么最后 y 方向的那一步就不需要了,答案减 1 代码 #include <iostream>#include <algorithm>#include <vector>#include <string>

【CF】C. Glass Carving(二分 + 树状数组 + 优先队列 + 数组计数)

这题简直蛋疼死。。。。。 A了一下午 #include<cstdio>#include<queue>#include<cstring>#include<algorithm>using namespace std;typedef long long LL;const int maxn = 200005;int h,w,n;int C1[maxn],C2[maxn];int

【CF】E. Anya and Cubes(双向DFS)

根据题意的话每次递归分3种情况 一共最多25个数,时间复杂度为3^25,太大了 我们可以分2次求解第一次求一半的结果,也就是25/2 = 12,记录结果 之后利用剩余的一半求结果 s-结果 = 之前记录过的结果 就可以 时间复杂度降低为 3 ^ (n/2+1) 题目链接:http://codeforces.com/contest/525/problem/E #include<set