【大联盟】20230516 T2 暑假最后一天(expert) 题解 P5326 【[ZJOI2019]开关】

大家可以猜猜看为什么有两个标题,因为这个原因本文就不设密码了。

题目描述

link

题解

这里记录下异或卷积的做法,我们记 \(f_s\) 表示到 \(s\) 的期望步数,那么:

\[f_s= \begin{cases} f_s=0 &s=\varnothing\\ f_s=1+\sum\limits_{s'=s\oplus {j}} f_{s'}p_j &s\ne\varnothing \end{cases} \]

我们令:

\[g_s= \begin{cases} -1 & s = \varnothing\\ p_i & s = \{i\}\\ 0 & |s| > 1 \end{cases} \]

\[h_s= \begin{cases} 2^n-1 & s = \varnothing\\ -1 & s \ne \varnothing\\ \end{cases} \]

由于 \(g\) 的和为 \(0\),则 \(h\) 的和也为 \(0\),则 \(h_{\varnothing}\) 的值为 \(2^n-1\)

所以,\(f*g=h\)

所以,\(FWT(f)*FWT(g)=FWT(h)\)

由于

\[FWT(g_s)=-1+\sum_{j=1}^{n}(-1)^{[j\in s]} p_j \]

\[FWT(h_s)= \begin{cases} 0 & s = \varnothing\\ 2^n & s \ne \varnothing\\ \end{cases} \]

因为如果 \(h_{\varnothing}=-1\)\(h_{s}=0\),所以现在,\(h_{s\ne \varnothing}=2^n\)

\[FWT(f_s)= \begin{cases} 1-\sum_{t}\frac{2^n}{1-\sum_{i}(-1)^{[i\in t]} p_i} & s = \varnothing\\ \frac{2^n}{-1+\sum_{i}(-1)^{[i\in S]} p_i} & s \ne \varnothing\\ \end{cases} \]

有一个结论,\(\sum_{i} FWT_i(f)=2^n f_{\varnothing}\)

所以,\(\sum_{i} FWT_i(f)=0\),于是计算出 \(f_{\varnothing}\)

于是,得到答案。

\[\begin{aligned} f_s&=IFWT_s(FWT(f))\\ &=\frac{1}{2^n}(f_{\varnothing}+\sum_{t\ne \varnothing} (-1)^{|s\cap t|}f_t)\\ &=\frac{1}{2^n}(\sum_{t\ne \varnothing} (-1+(-1)^{|s\cap t|})\frac{2^n}{-1+\sum_{i}(-1)^{[i\in s]} p_i})\\ &=\sum_{t\ne \varnothing} \frac{-2(|s\cap t| \bmod 2)}{-1+\sum_{i}(-1)^{[i\in s]} p_i}\\ &=\sum_{t\ne \varnothing} \frac{2(|s\cap t| \bmod 2)}{2\sum_{i}[i\in s] p_i}\\ &=\sum_{t\ne \varnothing} \frac{|s\cap t| \bmod 2}{\sum_{i\in s} p_i}\\ \end{aligned} \]

然后 DP 计算即可。

时间复杂度 \(O(n\sum_i {p_i})\)

代码

#include <bits/stdc++.h>
#define SZ(x) (int) x.size() - 1
#define all(x) x.begin(), x.end()
#define ms(x, y) memset(x, y, sizeof x)
#define F(i, x, y) for (int i = (x); i <= (y); i++)
#define DF(i, x, y) for (int i = (x); i >= (y); i--)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
template <typename T> void chkmax(T& x, T y) { x = max(x, y); }
template <typename T> void chkmin(T& x, T y) { x = min(x, y); }
template <typename T> void read(T &x) {
	x = 0; int f = 1; char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
	x *= f;
}
const int N = 110, M = 50010, MOD = 998244353;
int n, dp[N][M][2], p[N], sum, ans;
bool s[N];
int power(int x, int y = MOD - 2) {
	int ans = 1;
	for (; y; x = (ll) x * x % MOD, y >>= 1)
		if (y & 1) ans = (ll) ans * x % MOD;
	return ans;
}
signed main() {
	read(n);
	F(i, 1, n) read(s[i]);
	F(i, 1, n) read(p[i]), sum += p[i];
	dp[0][0][0] = 1;
	F(i, 1, n)
		F(j, 0, sum)
			F(k, 0, 1)
				dp[i][j][k] = ((j >= p[i] ? dp[i - 1][j - p[i]][k ^ s[i]] : 0) + dp[i - 1][j][k]) % MOD;
	F(i, 1, sum) ans = (ans + (ll) dp[n][i][1] * power(i)) % MOD;
	cout << (ll) ans * sum % MOD;
	return 0;
}
posted @ 2023-05-18 21:05  zhaohaikun  阅读(48)  评论(0编辑  收藏  举报