FWT
快速沃尔什变换
P4717 【模板】快速莫比乌斯/沃尔什变换 (FMT/FWT)
或卷积
思路就是把卷积转化为 $ O(n) $ 点积,类似于FFT。
考虑这样一个性质: $ i|j = i , i|k = i \Rightarrow i | (j|k) = i $ 。
令 $ FWT[A_i] = \sum_{i|j = i} A_j $ ,可以得到:
现在只要快速实现变换和逆变换,就能完美解决问题。
按照FFT分治思路,每次根据当前位的值是0是1分成两个子问题:$ A = A_0 + A_1 $
显然有 $ FWT[A] = merge( FWT[A_0] , FWT[A_0] + FWT[A_1] ) $
其中 merge
表示将两个多项式拼接起来, +
表示两个多项式按位相加。
CODE
void OR(ll *x,int len){
for(int i=1;i<len;i<<=1)
for(int j=0;j<len;j+=(i<<1))
for(int k=0;k<i;k++)
x[j+k+i]=(x[j+k+i]+x[j+k])%mod;
}
void IOR(ll *x,int len){
for(int i=1;i<len;i<<=1)
for(int j=0;j<len;j+=(i<<1))
for(int k=0;k<i;k++)
x[j+k+i]=(x[j+k+i]-x[j+k]+mod)%mod;
}
与卷积
几乎没什么区别。
CODE
void AND(ll *x,int len){
for(int i=1;i<len;i<<=1)
for(int j=0;j<len;j+=(i<<1))
for(int k=0;k<i;k++)
x[j+k]=(x[j+k]+x[j+k+i])%mod;
}
void IAND(ll *x,int len){
for(int i=1;i<len;i<<=1)
for(int j=0;j<len;j+=(i<<1))
for(int k=0;k<i;k++)
x[j+k]=(x[j+k]-x[j+k+i]+mod)%mod;
}
异或卷积
定义 $ x \oplus y $ 代表 \(x\) 和 \(y\) 按位异或, $ x \otimes y $ 代表 $ \text{popcount}( x \oplus y ) \bmod 2 $
观察性质: $ i \otimes ( j \oplus k ) = ( i \otimes j ) \oplus ( i \otimes k ) $
CODE
void XOR(ll *x,int len){
for(int i=1;i<len;i<<=1){
for(int j=0;j<len;j+=(i<<1)){
for(int k=0;k<i;k++){
x[j+k]=(x[j+k]+x[j+k+i])%mod;
x[j+k+i]=(x[j+k]-x[j+k+i]*2+mod*2)%mod;
}
}
}
}
void IXOR(ll *x,int len){
for(int i=1;i<len;i<<=1){
for(int j=0;j<len;j+=(i<<1)){
for(int k=0;k<i;k++){
ll fir=(x[j+k]+x[j+k+i])*ny2%mod;
ll sec=(x[j+k]-x[j+k+i]+mod)*ny2%mod;
x[j+k]=fir;
x[j+k+i]=sec;
}
}
}
}
例题
P3175 [HAOI2015] 按位或
题意:维护一个数字 \(x\) ,开始时是0,每次在 $ [0,2^n) $ 中随机一个数,第 \(i\) 个数的概率为 $ p_i $ ,进行操作 $ x \leftarrow x \oplus i $ ,问 $ x = 2^n -1 $ 的期望操作次数。 $ n \le 20 $
一个 $ O(3^n) $ 的暴力是显然的,不过没什么前途。
前置知识:min-max
容斥
简单证明一下:
不妨先假设所有元素互不相同,相同的可以扰动一下,不影响结果。
对于一个元素 \(x\) ,它在 \(S\) 中排名为第 \(k\) 小,显然包含它的子集 \(T\) 有 $ 2^{n-k} $ 个,其中 $ 2^{n-k-1} $ 个子集大小是奇数,另外 $ 2^{n-k-1} $ 个是偶数,两者相消结果是0。一个例外是 $ k=n $ ,即 \(x\) 是最大值,只会统计一次。证毕。
以上两个式子可以直接套上期望。
在本题中,设 \(S\) 中元素为每一位变成1的操作次数,$ \max(S) $ 就是 \(x\) 变成 $ 2^n - 1 $ 的操作次数。
注意到
容斥一下再跑FWT即可。
复杂度 $ O(2^n n) $
P5387 [Cnoi2019] 人形演舞
打表或者直接发现:$ SG( 2^k + p ) = p+1 , p < 2^k $
上SG定理,当 $ \text{mex}_{i=1}^{n} { SG(x_i) } $ 不为0时,先手必胜。
快速幂套FWT。$ O( m (\log m + \log n) ) $