FMT与子集卷积

FMT与子集卷积

C x = ∑ i ⋃ j = x a i ∗ b j C_x = \sum_{i\bigcup j = x}a_i*b_j Cx=ij=xaibj

sol.

构造一个 F M T ( A ) = ∑ i ⊂ x a i FMT(A) = \sum_{i\subset x}a_i FMT(A)=ixai
F M T x ( A ) ∗ F M T x ( B ) = ∑ k ⊂ x ∑ i ⋃ j = k a i ∗ b j = ∑ k ⊂ x C k = F M T x ( C ) FMT_x(A) * FMT_x(B) = \sum_{k \subset x}\sum_{i \bigcup j = k}a_i*b_j\\ =\sum_{k \subset x}C_k\\ = FMT_x(C) FMTx(A)FMTx(B)=kxij=kaibj=kxCk=FMTx(C)


考虑如何快速构造这个 F M T ( A ) FMT(A) FMT(A)


很显然的一个事情 F M T ( A ) = F M T ( A 0 ) + F M T ( A 1 ) [ 用 二 进 制 表 示 集 合 , 分 别 有 没 由 前 面 的 第 一 个 元 素 ] FMT(A) = FMT(A_0) + FMT(A1) [用二进制表示集合,分别有没由前面的第一个元素] FMT(A)=FMT(A0)+FMT(A1)[]

那么可以直接二进制倍增来写。。。

for(int len = 2 ; len <= n ; len = (len << 1)){
    for(int i = 0 ; i <= n ; i = i + len){
        for(int j = 0 ; j < (len >> 1) ; j++){
            f[i + j + (len >> 1)] += f[i + j];
        }
    }
}

大概就像这样就可以了

逆FMT的话如下

for(int len = 2 ; len <= n ; len = (len << 1)){
    for(int i = 0 ; i <= n ; i = i + len){
        for(int j = 0 ; j < (len >> 1) ; j++){
            f[i + j] -= f[i + j + (len >> 1)];
        }
    }
}

就可以做掉了。。。。

FWT是这个玩意的加强版,专门来处理二进制操作卷积的

o r or or卷积,就是上面的FMT

a n d and and卷积:

需要构造一个 F M T ( A ) FMT(A) FMT(A)使得, F W T ( A ) x ∗ F W T ( B ) x = F W T ( C ) x FWT(A)_x * FWT(B)_x = FWT(C)_x FWT(A)xFWT(B)x=FWT(C)x

即:
∑ i & x = x a i ∗ ∑ j & x = x b j = ∑ ( i & j ) & x = x a i ∗ b j = ∑ i & x = x c i \sum_{i \& x = x}a_i* \sum _ {j \& x = x}b_j = \sum_{(i \& j) \& x = x}a_i * b_j = \sum_{i \& x = x}c_i i&x=xaij&x=xbj=(i&j)&x=xaibj=i&x=xci

所以需要构造出:
F W T x ( A ) = ∑ i & x = x a i FWT_x(A) = \sum_{i \& x = x}a_i FWTx(A)=i&x=xai

FWT1

大概就是这样

for(int len = 2 ; len <= n ; len = (len << 1)){
    for(int i = 0 ; i <= n ; i = i + len){
        for(int j = 0 ; j < (len >> 1) ; j++){
            f[i + j] = f[i + j] + f[i + j + (len >> 1)];
        }
    }
}

xor卷积:

需要构造一个 F M T ( A ) FMT(A) FMT(A)使得, F W T ( A ) x ∗ F W T ( B ) x = F W T ( C ) x FWT(A)_x * FWT(B)_x = FWT(C)_x FWT(A)xFWT(B)x=FWT(C)x


∑ i   x o r   x   =   x a i ∑ j   x o r   x   =   x b j = \sum_{i \ xor\ x\ =\ x}a_i \sum_{j \ xor \ x \ = \ x}b_j = i xor x = xaij xor x = xbj=

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vgia3cKl-1613121592741)(C:\Users\Administrator\Desktop\笔记\FWT2.PNG)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5jsO5avm-1613121592758)(C:\Users\Administrator\Desktop\笔记\FWT3.PNG)]

补一个证明
g ( x , j ) ∗ g ( x , k ) = ( − 1 ) ∣ j ⋂ x ∣ + ∣ k ⋂ x ∣ = ( − 1 ) ( j   x o r   k ) ⋂ x g(x,j) * g(x , k) = (-1)^{|j\bigcap x| + |k\bigcap x|} = (-1)^{(j \ xor \ k) \bigcap x} g(x,j)g(x,k)=(1)jx+kx=(1)(j xor k)x
很显然的东西吖。。。。

所以就有代码

for(int len = 2 ; len <= n ; len = (len << 1)){
    for(int i = 0 ; i <= n ; i += len){
        for(int j = 0 ; j < (len << 1) ; j++){
            int A = f[i + j] , B = f[i + j + k];
            f[i + j] = A + B;
            f[i + j + k] = A - B;
        }
    }
}

很显然的吧

逆的话,代码如下

for(int len = 2 ; len <= n ; len = (len << 1)){
    for(int i = 0 ; i <= n ; i += len){
        for(int j = 0 ; j < (len << 1) ; j++){
            int A = f[i + j] , B = f[i + j + k];
            f[i + j] = (A + B) / 2;
            f[i + j + k] = (A - B) / 2;
        }
    }
}

FWT可以用来做一些高维前缀和的问题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ibOaQY33-1613121592772)(C:\Users\Administrator\Desktop\笔记\FWT4.PNG)]

很显然就是 A L L = ∑ ( − 1 ) ∣ 与 n o w 相 关 的 维 度 ∣ a n o w ALL = \sum (-1)^{|与now相关的维度|}a_{now} ALL=(1)nowanow

与上面异或的定义 g ( x , i ) g(x,i) g(x,i)非常的相似(实际上就是同一个玩意)

实际上就是一个xor卷积的事情。。。。

入门题:luoguP3175 [HAOI2015]按位或

很容易列出方程
f [ i ] = ∑ j ∑ ( k ∣ j )   =   i ( f [ k ] + 1 ) ∗ p [ j ] f [ i ] = ∑ j ! = i ∑ ( k ∣ j )   =   i ( f [ k ] + 1 ) ∗ p [ j ] + ∑ k ∣ i   =   i ( f [ i ] + 1 ) ∗ p [ k ] f [ i ] = ∑ j ! = i ∑ ( k ∣ j )   =   i ( f [ k ] + 1 ) ∗ p [ j ] + ∑ k ∣ i   =   i p [ k ] 1 − ∑ k ∣ i   =   i p [ k ] f[i] = \sum_{j}\sum_{(k|j) \ =\ i}(f[k] + 1) * p[j]\\ f[i] = \sum_{j != i}\sum_{(k|j) \ =\ i}(f[k] + 1) * p[j] + \sum_{k | i\ =\ i}(f[i] + 1) * p[k]\\ f[i] = \frac {\sum_{j != i}\sum_{(k|j) \ =\ i}(f[k] + 1) * p[j] + \sum_{k | i\ =\ i}p[k]} {1 - \sum_{k | i\ =\ i}p[k]} f[i]=j(kj) = i(f[k]+1)p[j]f[i]=j!=i(kj) = i(f[k]+1)p[j]+ki = i(f[i]+1)p[k]f[i]=1ki = ip[k]j!=i(kj) = i(f[k]+1)p[j]+ki = ip[k]

s o l 1. 解 决 分 母 的 快 速 计 算 , 直 接 对 { p } 做 一 个 f w t 就 好 了 , s o l 2. 分 子 第 二 项 同 s o l 1. s o l 3. 分 子 第 一 项 最 烂 每 一 次 都 要 做 一 个 F W T O ( 2 n ∗ 2 n ∗ n ) sol1.解决分母的快速计算,直接对\{p\}做一个fwt就好了,\\ sol2.分子第二项同sol1.\\ sol3.分子第一项最烂每一次都要做一个FWT\\ O(2^n * 2 ^ n * n) sol1.{p}fwtsol2.sol1.sol3.FWTO(2n2nn)
很显然是不行的吧。。。

本人只能想到这种。。。

如果能做到动态维护 FWT卷积的话,这个式子还是很好做的。。。

。。。。

正解是 min-max容斥。。。。

我先去补一下二项式反演的坑

就好了,\
sol2.分子第二项同sol1.\
sol3.分子第一项最烂每一次都要做一个FWT\
O(2^n * 2 ^ n * n)
$$
很显然是不行的吧。。。

本人只能想到这种。。。

如果能做到动态维护 FWT卷积的话,这个式子还是很好做的。。。

。。。。

正解是 min-max容斥。。。。

我先去补一下二项式反演的坑

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值