ARC132E题解

简要题意

\(n\) 个方块,每个方块有一个初始状态可能为左右或者空。每次操作随机选择一个空进行操作。每次操作可以向左或者向右走一直到下一个空或者走出边界,走到的每个格子会变成左或者右,这取决于移动方向。

求无法操作时方格为左的期望数。

数据范围:\(n\le 10^5\)

题解

首先看到这个操作我们可以把每一段方格看成一个整体,以空为分界线,然后最自然的思路就是对于每一个整体考虑对答案的贡献。

然后大概说一下我的想法。就是对于第 \(i\) 个连续段考虑它被更新过和没被更新过两种状态下的贡献。

  • 对于没被更新的情况,需要满足对于它左边的空都向左走,右边的空都向右走,贡献就是原始区间中左方格的个数。
  • 对于被更新的情况,如果最后被左边向右的覆盖则无贡献,否则就贡献区间长度。

然后经过一番推导你会发现,第二种情况求解的复杂度似乎是 \(O(n)\) 的,然后就炸了。所以我们需要优化一下思路。

我们可以从最终状态入手。

考虑最终的方格状态一定是左边一段左方格,右边一段右方格,然后中间的一段是原始状态。原因显然。

所以我们只用讨论最后哪一段没有被覆盖过,直接枚举是 \(O(n)\) 的。然后对于每一段,它左边的格子都有贡献,它本身的贡献是它原始贡献,它的右边没有贡献。于是我们只用算出它的系数就能求解问题了。

于是我们可以设计一个状态 \(f_n\) 表示让 \(n\) 个连续段都向左且不影响右边放个的状态的概率,考虑从 \(f_{n-1}\) 转移。因为只有最后一个空选择向右走才会不合法,于是就把第 \(n-1\)选择方法解放了,所以转移就是 \(f_n=f_{n-1}\times(1-\frac{1}{2n-2})\)

然后对于枚举段的右边和左边其实是等价的,所以这段的答案就是 \(f_{left}\times f_{right}\times(\operatorname{cnt}_{left}+\operatorname{original}_i)\)

其中 \(\operatorname{cnt}\) 是前缀个数,\(\operatorname{original}\) 是当前段原始左方格数。

代码

signed main(){
	for(int i = 1; i <= n; ++i)
		if(a[i] == '<')++cnt;
		else if(a[i] == '.')s[++tot] = i, c[tot] = cnt;
	c[++tot] = cnt; f[1] = 1;
	for(int i = 2; i <= tot; ++i)f[i] = 1ll * f[i - 1] * (p + 1 - qmi(2 * i - 2, p - 2)) % p;
	for(int i = 1; i <= tot; ++i)ans = (0ll + ans + 1ll * f[i] * f[tot - i + 1] % p * (c[i] - c[i - 1] + s[i - 1])) % p;
}
posted @ 2024-12-14 11:59  Lyrella  阅读(34)  评论(0)    收藏  举报