[ARC193B] Broken Wheel 做题记录

[ARC193B] Broken Wheel

[ARC193B] Broken Wheel

Solution

约定:每个点的编号都加一。

首先考虑问题的弱化版:所有点与 \(n+1\) 都没有连边。

Lemma 1:在这种情况下,把入度为 \(1\) 的点删除后,要么没有剩下的点,要么剩下的点的入度 \(0,2\) 交替。

正确性显然。

接下来我们考虑一般的情况。

可以发现,由于图上的边的数量一定,那么 \(1\sim n\) 中的点入度确定之后,\(n+1\) 号点入度也确定了。

普通点的处理是简单的,下面来考虑如何处理特殊点。

对于一个特殊点 \(x\),分四种情况讨论:

  1. \(d_x=3\),我们把 \(n\) 号点向 \(x\) 连的边删去,就变成了 普通 \(2\)
  2. \(d_x=2\),若 \(n\) 没有向 \(x\) 连边,那么就是普通 \(2\);否则,删去这条边之后就会变为 \(1\)。那么这样的 \(x\) 可以看作 可变 \(2\)
  3. \(d_x=1\),若 \(n\) 没有向 \(x\) 连边,那么就是普通 \(1\);否则,删去这条边之后就会变为 \(0\)。那么这样的 \(x\) 可以看作 可变 \(0\)
  4. \(d_x=0\),直接看作普通 \(0\)

于是题意转化为:

对于普通点,可以从 \(0,1,2\) 中选择;

对于特殊点,可以从 普通 \(0\)、可变 \(0\)、普通 \(2\)、可变 \(2\) 中选择。

一个环形序列合法,当且仅当通过调整 可变 \(0\) 与可变 \(2\) 的取值之后,把入度为 \(1\) 的点删除后,要么没有剩下的点,要么剩下的点的入度 \(0,2\) 交替。

对合法的环形序列计数。

合法的环形序列具有什么性质,能够让我们方便地进行 dp 呢?

Lemma 2:一个序列合法,当且仅当每两个 普通 \(0\) 之间存在一个 普通 \(2\) 或 可变 \(2\),每两个 普通 \(2\) 之间存在一个 普通 \(0\) 或 可变 \(0\)

必要性显然。

再证充分性。我们把每两个普通 \(0\) 拿出来,若它们之间没有可变 \(0\),那么就随便挑一个可变 \(0\) 出来变为 \(0\),其他的都变为 \(1\);否则,所有的可变 \(0\) 都变为 \(1\)。对于普通 \(2\) 同理。那么得出的序列一定合法。

有了这个性质,我们就能 dp 了。

首先考虑链怎么做。设 \(f_{x,0/1/2,0/1}\) 表示到了第 \(x\) 个点,上一个普通 \(0/2\) 是 普通 \(0\) / 没出现 / 普通 \(2\),上一个普通 \(0/2\) 后面有没有出现可变 \(0/2\)。转移枚举所有情况即可。

接下来我们考虑怎么把链的两段接起来。

我们摒弃第二维的 \(1\)。先给 \(f_0\) 钦定一个初始状态,最后只保留 \(f_n\) 对应的状态即可。

但我们此时没有办法统计到不存在普通 \(0/2\) 的情况。那么我们单独计算这一部分的答案,设特殊点的数量为 \(c\),这一部分的答案就是 \(2^c\)

此时还有一个问题:转移的过程中可能也不会选择普通 \(0/2\),直接回到环的起点。那么我们再加一维 \(0/1\) 表示当前有没有选择普通 \(0/2\) 即可。

int n;
char a[N];

const ll mod=998244353;

inline ll Mod(ll x){return (x>=mod)?(x-mod):(x);}

inline void Add(ll &x,ll y){x=Mod(x+y);}

ll ans,f[N][3][2][2];

void DpSolve(){
	for(int i=0;i<=n;i++){
		for(int j=0;j<=1;j++){
			Add(f[i+1][0][0][1],Mod(f[i][2][0][j]+f[i][2][1][j])); //普通0
			Add(f[i+1][0][0][1],f[i][0][1][j]);//普通0
			Add(f[i+1][2][0][1],Mod(f[i][0][0][j]+f[i][0][1][j])); //普通2
			Add(f[i+1][2][0][1],f[i][2][1][j]);//普通2
			if(a[i+1]=='0'){
				Add(f[i+1][0][0][j],f[i][0][0][j]);//1 
				Add(f[i+1][0][1][j],f[i][0][1][j]);
				Add(f[i+1][2][0][j],f[i][2][0][j]);
				Add(f[i+1][2][1][j],f[i][2][1][j]);
			}else{
				Add(f[i+1][0][0][j],f[i][0][0][j]);//可删0 
				Add(f[i+1][0][1][j],f[i][0][1][j]);//可删0 
				Add(f[i+1][2][1][j],Mod(f[i][2][0][j]+f[i][2][1][j]));//可删0 
				Add(f[i+1][2][0][j],f[i][2][0][j]);//可删2
				Add(f[i+1][2][1][j],f[i][2][1][j]);//可删2 
				Add(f[i+1][0][1][j],Mod(f[i][0][0][j]+f[i][0][1][j]));//可删2
			}
		}
	}
}

signed main(){
	read(n);
	scanf("%s",a+1);
	ll res=1;
	for(int i=1;i<=n;i++)
		if(a[i]=='1') res=(Mod(res<<1));
	ans=res;
	memset(f,0,sizeof(f));
	f[0][0][0][0]=1; DpSolve(); Add(ans,f[n][0][0][1]);
	memset(f,0,sizeof(f));
	f[0][0][1][0]=1; DpSolve(); Add(ans,f[n][0][1][1]);
	memset(f,0,sizeof(f));
	f[0][2][0][0]=1; DpSolve(); Add(ans,f[n][2][0][1]);
	memset(f,0,sizeof(f));
	f[0][2][1][0]=1; DpSolve(); Add(ans,f[n][2][1][1]);
	printf("%lld\n",ans);
	return 0;
}
posted @ 2025-03-09 09:03  XP3301_Pipi  阅读(44)  评论(0)    收藏  举报
Title