传送门
这道题目前知道的推导原理本质不同做法有两种,另一种是生成函数:here
题解:
设 p i p_i pi表示在单次操作中选择了第 i i i个开关的概率,设 U U U表示所有开关的 2 n 2^n 2n种不同状态的集合,设集合幂级数 F ( x ) = ∑ T ⊆ U f T x T F(x)=\sum_{T\subseteq U}f_Tx^T F(x)=∑T⊆UfTxT,其中 f T f_T fT表示 s i = [ i ∈ T ] s_i=[i\in T] si=[i∈T]状态下打开门需要的期望步数。
对于
T
!
=
∅
T!=\empty
T!=∅,显然有
f
T
=
1
+
∑
i
=
1
n
p
i
f
T
⊕
i
f_T=1+\sum\limits_{i=1}^np_if_{T\oplus i}
fT=1+i=1∑npifT⊕i
对于
T
=
∅
T=\empty
T=∅,显然有
f
∅
=
0
f_\empty=0
f∅=0
发现转移是一个异或卷积,考虑构造 G ( x ) = ∑ i p i x i G(x)=\sum_{i}p_ix^i G(x)=∑ipixi,那么式子写出来就是 F = ∑ T ⊆ U x T + F ⋅ G + c x ∅ F=\sum_{T\subseteq U}x^T+F\cdot G+cx^\empty F=T⊆U∑xT+F⋅G+cx∅
这里 c c c是一个修正用的常数。
解异或卷积方程一般的通用方法就是FWT过去再IFWT回来。
先把式子写成 F ( 1 − G ) = ∑ T ⊆ U x T + c x ∅ F(1-G)=\sum_{T\subseteq U}x^T+cx^\empty F(1−G)=∑T⊆UxT+cx∅,然后FWT,设 F F F进行FWT后得到 F ^ \hat F F^,其各项系数为 f ^ \hat f f^, G G G同理。
考虑FWT后的形式,我们得到:
f ^ S ( 1 − g ^ S ) = ∑ T ( − 1 ) ∣ T ∩ S ∣ + c \hat f_S(1-\hat g_S)=\sum_{T}(-1)^{|T\cap S|}+c f^S(1−g^S)=T∑(−1)∣T∩S∣+c
令 S = ∅ S=\empty S=∅,显然有 g S = ∑ p i = 1 g_S=\sum p_i=1 gS=∑pi=1,则得到 c = − 2 n c=-2^n c=−2n
令 s ! = ∅ s!=\empty s!=∅,得到 f ^ S = c 1 − g ^ s \hat f_S=\dfrac{c}{1-\hat g _s} f^S=1−g^sc
再IFWT回去得到:
f S = 1 2 n ∑ T ( − 1 ) ∣ T ∩ S ∣ f ^ T = f ^ ∅ 2 n − ∑ T ≠ ∅ ( − 1 ) ∣ T ∩ S ∣ 1 1 − g ^ T f_S=\frac{1}{2^n}\sum_{T}(-1)^{|T\cap S|}\hat f_T=\frac{\hat f_{\empty}}{2^n}-\sum_{T\neq\empty}(-1)^{|T\cap S|}\frac{1}{1-\hat g_T} fS=2n1T∑(−1)∣T∩S∣f^T=2nf^∅−T=∅∑(−1)∣T∩S∣1−g^T1
令 S = ∅ S=\empty S=∅,由于 f ∅ = 0 f_\empty=0 f∅=0,得到 f ^ ∅ 2 n = ∑ T ≠ ∅ 1 1 − g ^ T \dfrac{\hat f_\empty}{2^n}=\sum_{T\neq \empty}\dfrac{1}{1-\hat g_T} 2nf^∅=∑T=∅1−g^T1
则答案就是: f S = ∑ T ≠ ∅ ( 1 − ( − 1 ) ∣ T ∩ S ∣ ) 1 1 − g ^ T = ∑ T ≠ ∅ [ ∣ T ∩ S ∣ ≡ 1 ( m o d 2 ) ] 2 1 − g ^ T = ∑ T ≠ ∅ [ ∣ T ∩ S ∣ ≡ 1 ( m o d 2 ) ] 2 1 − ∑ i ∉ T p i + ∑ i ∈ T p i = ∑ T ≠ ∅ [ ∣ T ∩ S ∣ ≡ 1 ( m o d 2 ) ] 1 ∑ i ∈ T p i f_S=\sum_{T\neq\empty}(1-(-1)^{|T\cap S|})\frac{1}{1-\hat g_T}\\ =\sum_{T\neq \empty}[|T\cap S|\equiv 1\pmod 2]\frac{2}{1-\hat g_T}\\ =\sum_{T\neq \empty}[|T\cap S|\equiv 1\pmod 2]\frac{2}{1-\sum\limits_{i\notin T}p_i+\sum\limits_{i\in T}p_i}\\ =\sum_{T\neq \empty}[|T\cap S|\equiv 1\pmod 2]\frac{1}{\sum\limits_{i\in T}p_i} fS=T=∅∑(1−(−1)∣T∩S∣)1−g^T1=T=∅∑[∣T∩S∣≡1(mod2)]1−g^T2=T=∅∑[∣T∩S∣≡1(mod2)]1−i∈/T∑pi+i∈T∑pi2=T=∅∑[∣T∩S∣≡1(mod2)]i∈T∑pi1
发现 ∑ p \sum p ∑p不是很大,直接背包即可,同时记录一维表示交的奇偶性最后直接算答案。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
using std::cerr;
using std::cout;
cs int mod=998244353;
inline int add(int a,int b){a+=b-mod;return a+(a>>31&mod);}
inline int dec(int a,int b){a-=b;return a+(a>>31&mod);}
inline int mul(int a,int b){ll r=(ll)a*b;return r>=mod?r%mod:r;}
inline void Inc(int &a,int b){a+=b-mod;a+=a>>31&mod;}
inline void Dec(int &a,int b){a-=b;a+=a>>31&mod;}
inline void Mul(int &a,int b){a=mul(a,b);}
cs int N=1e2+7,M=5e4+7;
int n;
int inv[M];
int s[N],p[N],a[M],b[M],P;
signed main(){
#ifdef zxyoi
freopen("button.in","r",stdin);
#endif
scanf("%d",&n);a[0]=1;
for(int re i=1;i<=n;++i)scanf("%d",s+i);
for(int re i=1;i<=n;++i)scanf("%d",p+i);
for(int re i=1;i<=n;++i){
int *a1=s[i]?b:a,*b1=s[i]?a:b,p=::p[i];
for(int re j=P;~j;--j)
Inc(a1[j+p],a[j]),Inc(b1[j+p],b[j]);
P+=p;
}
int ans=b[1];inv[1]=1;
for(int re i=2;i<=P;++i){
inv[i]=mul(mod-mod/i,inv[mod%i]);
Inc(ans,mul(b[i],inv[i]));
}
cout<<mul(ans,P)<<"\n";
return 0;
}