题解 开心消消乐
神仙题
首先令 表示到点 的状态为 可以 求出合法的消除操作序列数
一个优化:令 为当前栈中情况,当 x=0 时返回 a,x=1 时返回 b
取或可以 完成没有 ? 的判定
于是考虑带上 ‘?’
我 tm 谢谢你
题解写得 很 简 洁
- DP 套 DP 貌似还可以用来处理合法状态数一算就重的情况
比如有并非对于数位限制的数位 DP 之类
于是考虑令 为当前状态是否满足加入 0/1 能得到 0/1
转移考虑预处理一个 表示 与 状态 能转移到哪个状态
于是转移就很简单了
那看这个东西怎么预处理
再预处理出 表示 与 能转移到哪些
于是从 a/b, c/d 中枚举全 1 对进行转移即可
状态数是
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define pb push_back
#define ll long long
//#define int long long
int n;
char c[N];
int val[N];
const ll mod=998244353;
inline void md(ll& a, ll b) {a+=b; a=a>=mod?a-mod:a;}
#if 0
namespace task1{
bool g[N][2];
void solve() {
memset(g, 0, sizeof(g));
for (int i=1; i<=n; ++i) s[i]-='0';
g[2][0]=val[(0<<2)|(s[2]<<1)|(s[1])];
g[2][1]=val[(1<<2)|(s[2]<<1)|(s[1])];
for (int i=4; i<=n; i+=2) {
int t=g[i-2][s[i-1]];
g[i][0]|=val[(0<<2)|(s[i]<<1)|t];
g[i][1]|=val[(1<<2)|(s[i]<<1)|t];
g[i][0]|=g[i-2][val[(0<<2)|(s[i]<<1)|(s[i-1])]];
g[i][1]|=g[i-2][val[(1<<2)|(s[i]<<1)|(s[i-1])]];
}
//for (int i=2; i<=n; i+=2) printf("g[%d][0]=%d, g[%d][1]=%d\n", i, g[i][0], i, g[i][1]);
cout<<g[n-1][s[n]]<<endl;
}
}
#endif
namespace task{
int tr[1<<4][1<<2];
ll f[N][1<<4], ans;
vector<int> buc[1<<2][1<<2];
void init() {
for (int s=0; s<4; ++s) {
for (int t=0; t<4; ++t) {
int k=(t&1)?(s>>1):(s&1);
//cout<<"k: "<<k<<endl;
buc[s][t].pb(val[(0<<2)|(t&2)|k]|(val[(1<<2)|(t&2)|k]<<1));
buc[s][t].pb( ((s&(1<<val[(0<<2)|t]))?1:0) | (((s&(1<<val[(1<<2)|t]))?1:0)<<1) );
sort(buc[s][t].begin(), buc[s][t].end());
buc[s][t].erase(unique(buc[s][t].begin(), buc[s][t].end()), buc[s][t].end());
}
}
for (int s=0; s<16; ++s) {
for (int t=0; t<4; ++t) {
for (int i=0; i<2; ++i) if (s&(1<<i)) {
for (int j=0; j<2; ++j) if (s&(4<<j)) {
int g=i|(j<<1);
for (auto it:buc[g][t]) {
//tr[s][t]|=1<<it, assert(it<4);
int k=0;
k |= ( (it&1) ? 2 : 1);
k |= ( (it&2) ? 8 : 4);
tr[s][t]|=k;
}
}
}
}
}
}
void solve() {
ans=0;
memset(tr, 0, sizeof(tr));
memset(f, 0, sizeof(f));
for (int s=0; s<4; ++s) for (int t=0; t<4; ++t) buc[s][t].clear();
init();
//for (int s=0; s<4; ++s) for (int t=0; t<4; ++t) {cout<<"buc of "<<bitset<2>(s)<<' '<<bitset<2>(t)<<": "; for (auto it:buc[s][t]) cout<<bitset<2>(it)<<' '; cout<<endl;}
//for (int s=0; s<16; ++s) for (int t=0; t<4; ++t) {cout<<"tr: "<<bitset<4>(s)<<' '<<bitset<2>(t)<<' '<<bitset<4>(tr[s][t])<<endl;}
for (int t=0; t<4; ++t) {
if ( (t&1 && c[1]=='0') || (!(t&1) && c[1]=='1') ) continue;
if ( (t&2 && c[2]=='0') || (!(t&2) && c[2]=='1') ) continue;
int s=0;
s |= ( (val[(0<<2)|t]) ? 2 : 1);
s |= ( (val[(1<<2)|t]) ? 8 : 4);
++f[2][s];
}
for (int i=4; i<=n; i+=2) {
//cout<<"i: "<<i<<endl;
for (int s=0; s<16; ++s) {
for (int t=0; t<4; ++t) {
if ( (t&1 && c[i-1]=='0') || (!(t&1) && c[i-1]=='1') ) continue;
if ( (t&2 && c[i]=='0') || (!(t&2) && c[i]=='1') ) continue;
//cout<<"st: "<<bitset<4>(s)<<' '<<bitset<2>(t)<<' '<<bitset<4>(tr[s][t])<<' '<<f[i-2][s]<<endl;
md(f[i][tr[s][t]], f[i-2][s]);
//cout<<f[i][tr[s][t]]<<endl;
}
}
}
for (int t=0; t<2; ++t) {
if (c[n]!='?' && c[n]-'0'!=t) continue;
for (int s=0; s<16; ++s) if (s&(1<<(t<<1|1)))
md(ans, f[n-1][s]);
}
#if 0
cout<<"f: "<<endl;
for (int i=2; i<=n; i+=2) {
for (int s=0; s<16; ++s) cout<<"f["<<i<<"]["<<bitset<4>(s)<<"]="<<f[i][s]<<endl;
}
#endif
cout<<ans<<endl;
}
}
signed main()
{
freopen("game.in", "r", stdin);
freopen("game.out", "w", stdout);
int T;
scanf("%d", &T);
while (T--) {
scanf("%s", c);
for (int i=0; i<8; ++i) val[i]=c[i]^48;
scanf("%s", c+1);
n=strlen(c+1);
task::solve();
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!