AGC022E Median Replace 题解 / 计数 dp

题目传送门:AGC022E Median Replace

考虑如何判断一个字符串,是否合法。

维护一个栈,满足这个栈从栈底到栈顶由一段连续的 \(1\) 和一段连续的 \(0\) 组成。

分为两种情况。

若加入的值为 \(0\),那么如果栈顶有两个 \(0\) 直接消去变成一个 \(0\),否则直接加入。

显然栈内最多只有两个 \(0\)

若加入的值为 \(1\),那么如果栈顶为 \(0\) 直接将其消去(因为一个数 $ \texttt{+01}$ 操作之后还是这个数),如果有栈顶有两个 \(1\),由于最多两个 \(0\),可以直接忽略,否则直接加入。

显然栈内最多只有两个 \(1\)

合法情况当且仅当最后的栈 \(1\) 的个数不少于 \(0\) 的个数。

先当于我们把栈内的情况从栈底写到栈顶只有这几种情况 \(\texttt{NULL,0,00,1,10,100,11,110,1100}\)

有如下的转换。

\[\texttt{NULL} \texttt{ + } \texttt{0} \to \texttt{0} \]

\[\texttt{0} \texttt{ + } \texttt{0} \to \texttt{00} \]

\[\texttt{00} \texttt{ + } \texttt{0} \to \texttt{0} \]

\[\texttt{1} \texttt{ + } \texttt{0} \to \texttt{10} \]

\[\texttt{10} \texttt{ + } \texttt{0} \to \texttt{100} \]

\[\texttt{100} \texttt{ + } \texttt{0} \to \texttt{10} \]

\[\texttt{11} \texttt{ + } \texttt{0} \to \texttt{110} \]

\[\texttt{110} \texttt{ + } \texttt{0} \to \texttt{1100} \]

\[\texttt{1100} \texttt{ + } \texttt{0} \to \texttt{110} \]


\[\texttt{NULL} \texttt{ + } \texttt{1} \to \texttt{1} \]

\[\texttt{0} \texttt{ + } \texttt{1} \to \texttt{NULL} \]

\[\texttt{00} \texttt{ + } \texttt{1} \to \texttt{0} \]

\[\texttt{1} \texttt{ + } \texttt{1} \to \texttt{11} \]

\[\texttt{10} \texttt{ + } \texttt{1} \to \texttt{1} \]

\[\texttt{100} \texttt{ + } \texttt{1} \to \texttt{10} \]

\[\texttt{11} \texttt{ + } \texttt{1} \to \texttt{11} \]

\[\texttt{110} \texttt{ + } \texttt{1} \to \texttt{11} \]

\[\texttt{1100} \texttt{ + } \texttt{1} \to \texttt{110} \]

\(f_{i,j}\) 表示前 \(i\) 个位置且状态为 \(j\) 的方法数,按照上面方法转移即可。

#include<bits/stdc++.h>
#define int long long
#define double long double
using namespace std;
const int N=3e5+10,mod=1e9+7;
inline int read(){
	char c=getchar();
	int f=1,ans=0;
	while(c<48||c>57) f=(c==45?f=-1:1),c=getchar();
	while(c>=48&&c<=57) ans=(ans<<1)+(ans<<3)+(c^48),c=getchar();
	return ans*f;
}
unordered_map<string,int>mp; 
int f[N][15];
main(){
	string s;cin>>s;int n=s.size();s=" "+s;
	mp["NULL"]=1;
	mp["0"]=2;
	mp["00"]=3;
	mp["1"]=4;
	mp["10"]=5;
	mp["100"]=6;
	mp["11"]=7;
	mp["110"]=8;
	mp["1100"]=9;
	f[0][mp["NULL"]]=1;
	for (int i=0;i<n;i++){
		if (s[i+1]=='0'||s[i+1]=='?') f[i+1][mp["0"]]=(f[i+1][mp["0"]]+f[i][mp["NULL"]])%mod;
		if (s[i+1]=='0'||s[i+1]=='?') f[i+1][mp["00"]]=(f[i+1][mp["00"]]+f[i][mp["0"]])%mod;
		if (s[i+1]=='0'||s[i+1]=='?') f[i+1][mp["0"]]=(f[i+1][mp["0"]]+f[i][mp["00"]])%mod;
		if (s[i+1]=='0'||s[i+1]=='?') f[i+1][mp["10"]]=(f[i+1][mp["10"]]+f[i][mp["1"]])%mod;
		if (s[i+1]=='0'||s[i+1]=='?') f[i+1][mp["100"]]=(f[i+1][mp["100"]]+f[i][mp["10"]])%mod;
		if (s[i+1]=='0'||s[i+1]=='?') f[i+1][mp["10"]]=(f[i+1][mp["10"]]+f[i][mp["100"]])%mod;
		if (s[i+1]=='0'||s[i+1]=='?') f[i+1][mp["110"]]=(f[i+1][mp["110"]]+f[i][mp["11"]])%mod;
		if (s[i+1]=='0'||s[i+1]=='?') f[i+1][mp["1100"]]=(f[i+1][mp["1100"]]+f[i][mp["110"]])%mod;
		if (s[i+1]=='0'||s[i+1]=='?') f[i+1][mp["110"]]=(f[i+1][mp["110"]]+f[i][mp["1100"]])%mod;
		if (s[i+1]=='1'||s[i+1]=='?') f[i+1][mp["1"]]=(f[i+1][mp["1"]]+f[i][mp["NULL"]])%mod;
		if (s[i+1]=='1'||s[i+1]=='?') f[i+1][mp["NULL"]]=(f[i+1][mp["NULL"]]+f[i][mp["0"]])%mod;
		if (s[i+1]=='1'||s[i+1]=='?') f[i+1][mp["0"]]=(f[i+1][mp["0"]]+f[i][mp["00"]])%mod;
		if (s[i+1]=='1'||s[i+1]=='?') f[i+1][mp["11"]]=(f[i+1][mp["11"]]+f[i][mp["1"]])%mod;
		if (s[i+1]=='1'||s[i+1]=='?') f[i+1][mp["1"]]=(f[i+1][mp["1"]]+f[i][mp["10"]])%mod;
		if (s[i+1]=='1'||s[i+1]=='?') f[i+1][mp["10"]]=(f[i+1][mp["10"]]+f[i][mp["100"]])%mod;
		if (s[i+1]=='1'||s[i+1]=='?') f[i+1][mp["11"]]=(f[i+1][mp["11"]]+f[i][mp["11"]])%mod;
		if (s[i+1]=='1'||s[i+1]=='?') f[i+1][mp["11"]]=(f[i+1][mp["11"]]+f[i][mp["110"]])%mod;
		if (s[i+1]=='1'||s[i+1]=='?') f[i+1][mp["110"]]=(f[i+1][mp["110"]]+f[i][mp["1100"]])%mod;
	}
	cout <<(f[n][mp["1"]]+f[n][mp["10"]]+f[n][mp["11"]]+f[n][mp["110"]]+f[n][mp["1100"]])%mod;
    return 0;
}
posted @ 2026-01-10 16:32  OTn53_qwq  阅读(25)  评论(0)    收藏  举报