Live2D

CF1383E Strange Operation 题解

link

Solution

shaber 题,但是又没有做出来。

我们发现这个变化相当于可以任意删掉 \(0\)\(1\) 的话只有与 \(1\) 相邻的时候可以删掉。那么相当于我们可以把一段包含 \(1\) 的段变成只包含 \(1\) 的段。

既然要对本质不同的变化串计数,那么我们可以考虑建 DFA。加 \(1\) 的话直接找后面第 \(1\)\(1\) 即可。加 \(0\) 的话如果当前为 \(1\) 或者下一个就是 \(0\) 的话我们直接找下一个 \(0\) 即可。那么需要考虑的就是当前为一段连续 \(0\) 的结尾,要加 \(1\)\(0\),那么我们就需要找到后面第一个 \(0\) 连续段大于当前连续段长度的当前连续短长度个 \(0\) 的下一位。因为你可以把中间的 \(1\)\(0\) 接在前面的 \(1\) 连续段之后,然后删掉,那么你就需要再取若干个 \(0\)。这个直接用个单调栈维护一下就好了。

那么相当于我们从 \(1\) 出发,再到任意一个 \(1\) 结尾即可,因为后面的部分全都可以删掉。

Code

#include <bits/stdc++.h>
using namespace std;
     
#define Int register int
#define mod 1000000007
#define MAXN 1000005

// char buf[1<<21],*p1=buf,*p2=buf;
// #define getchar() (p1==p2 && (p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}

char str[MAXN];int n,m,f[MAXN],g[MAXN][2];

int mul (int a,int b){return 1ll * a * b % mod;}
int dec (int a,int b){return a >= b ? a - b : a + mod - b;}
int add (int a,int b){return a + b >= mod ? a + b - mod : a + b;}
int qkpow (int a,int b){
	int res = 1;for (;b;b >>= 1,a = mul (a,a)) if (b & 1) res = mul (res,a);
	return res;
}
void Add (int &a,int b){a = add (a,b);}
void Sub (int &a,int b){a = dec (a,b);}

int top,sta[MAXN],len[MAXN],edp[MAXN];

signed main(){
	scanf ("%s",str + 1),n = strlen (str + 1);
	int L = 1;while (str[L] == '0') ++ L;
	int R = n;while (str[R] == '0') -- R;
	if (L > R){write (n),putchar ('\n');return 0;}
	for (Int x = R,lst = 0;x >= L;-- x){
		g[x][1] = lst;
		if (str[x] == '1') lst = x;
	}
	for (Int x = R,lst = 0;x >= L;-- x){
		if (str[x] == '1' || str[x + 1] == '0') g[x][0] = lst;
		if (str[x] == '0') lst = x;
	}
	for (Int x = L,sum = 0;x <= R;++ x){
		if (str[x] == '0'){
			sum ++;
			while (top && len[top] < sum) g[edp[top --]][0] = x;
		}
		else ++ top,len[top] = sum,edp[top] = x - 1,sum = 0;
	}
	f[L] = 1;int ans = 0;
	for (Int x = L;x <= R;++ x){
		if (str[x] == '1') Add (ans,f[x]);
		for (Int t = 0;t < 2;++ t) if (g[x][t]) Add (f[g[x][t]],f[x]);
	}
	write (mul (mul (L,n - R + 1),ans)),putchar ('\n');
	return 0;
}
posted @ 2022-11-21 08:37  Dark_Romance  阅读(33)  评论(0编辑  收藏  举报