zoukankan      html  css  js  c++  java
  • $ ext {FWT}$学习笔记

    ( ext {FWT}) 学习笔记

    正常项的( ext {FWT})

    ( ext {OI})中,我们经常会碰到这种问题:

    • 给出一个长度为(n)的序列(a_{1,2,...,n},b_{1,2,...,n}),求出

    [c_k=sum_{ioplus j=k}a_i b_j ]

    其中(oplus)是定义的一种二进制下的运算。

    对于这种问题,我们有一种通用的方法,我们称之为( ext {FWT})

    我们考虑对于一个(A)构造一个(FWT)变换序列,满足:

    [forall A imes B=C,FWT[A]star FWT[B]=FWT[C] ]

    其中( imes)就是上文定义的卷积,(star)是按位乘法。

    我们考虑定义一种二进制运算的函数(c(i,j)),满足:

    [FWT[A]_i=sum_{j=0}^{n} c(i,j) A_j ]

    于是,我们可以得到:

    若存在:

    [C=A imes B ]

    则有:

    [FWT[C]_i=sum_{j=0}^{n} c(i,j)sum_{koplus d=j} A_kB_d ]

    [=sum_{j=0}^{n} sum_{koplus d=j} c(i,koplus d) A_k B_d ]

    而我们根据(FWT)的定义我们又可以得到:

    [FWT[C]_i=FWT[A]_i imes FWT[B]_i=(sum_{j=0}^{n} c(i,j)A_j) imes (sum_{j=0}^{n} c(i,j)B_j) ]

    [=sum_{j=0}^{n} sum_{k=0}^{n} c(i,j) c(i,k)A_j B_k ]

    于是,我们就可以得到:

    [c(i,j)c(i,k)=c(i,joplus k) ]

    不过因为是在二进制下的运算,所以一般构造的话都会满足

    [i=(i_1i_2...i_n)_2 ]

    则满足:

    [c(i,j)=c(i_1,j_1)c(i_2,j_2)...c(i_n,j_n) ]

    于是,我们只需要知道(c(0/1,0/1))即可。

    但是,我们现在仅仅可以在(Theta(n^2))的时间复杂度内求出和转换(FWT[A]),显然不能满足我们的对优秀的时间的渴求。

    我们想一下在( ext {FFT})中,我们是如何做到(Theta(nlog n))转换的?分治!!!我们在( ext {FWT})中也可以用类似的方法。

    我们考虑对于当前的(FWT[A]_i)应该如何求出。

    可以得到:

    [FWT[A]_i=sum_{j=0}^{n} c(i,j)A_j ]

    [=sum_{j=0}^{n/2-1} c(i_1,0) A_j+sum_{j=n/2}^{n} c(i_1,1)A_j ]

    [=c(i_1,0)FWT[A_0]_i+c(i_1,1)FWT[A_1]_i ]

    其中(FWT[A_0/A_1])就是子集的一个变换,与( ext {FFT})类似。

    我们发现如果我们构造转移矩阵:

    [ ext {mat}=egin{bmatrix}c_{0,0} ,c_{0,1}\ c_{1,0},c_{1,1} end{bmatrix} ]

    其实(A o FWT[A])每一次变换就是乘上( ext {mat}),那么(FWT[A] o A)就是乘上( ext {mat})的逆矩阵。逆矩阵直接手动构造即可。

    一些例子

    (wedge)

    对于并卷积,我们可以构造(c(i,j)=[j|i]),其中([j|i])表示的是二进制下的(j)是二进制下的(i)的子集(每一位(0/1)相当于该元素是否在当前集合出现)。

    (vee)

    对于或卷积,我们可以构造(c(i,j)=[i|j])

    (oplus)

    对于异或卷积,我们可以构造(c(i,j)=(-1)^{|iwedge j|})

    模板题

    就是上面三种运算的总和,代码戳这里打开

    非模板的一些例子

    CF449D Jzzhu and Numbers

    CF1119H Triple + 题解 link

    ( ext {FST})

    我们需要解决这样一个问题:

    • 给出一个长度为(n)的序列(a_{1,2,...,n},b_{1,2,...,n}),求出:

    [c_i=sum_{jvee k=i,jwedge k=0} a_j b_k ]

    对于这个问题,如果没有(jwedge k=0)的话,这就是一个板的( ext {FWT}) (vee)运算。我们发现其实(jwedge k=0)的条件就相当于(|j|+|k|=|jvee k|),于是,我们可以设二维数组(f_i),我们可以设转移式:

    [f_i=sum_{j=0}^{i} h_j w_{i-j} ]

    其中(h_{i,j}=[|j|=i]a_j,w_{i,j}=[|j|=i]b_j)

    很显然,最后的(c_i=f_{|i|,i})

    于是,我们就可以在(Theta(nlog^ 2 n))的时间复杂度内解决这个问题。

    代码戳这里打开

    (k)进制下的( ext {FWT})

    我们发现上面的这个东西其实都是在(2)进制下面计算的,那么如果我们要拓展到(k)进制我们应该怎么办呢?

    很显然,我们应该定义广义的(wedge,vee,oplus)

    • $wedge $

    (k)进制下,定义(awedge b=min{a,b})

    • (vee)

    (k)进制下,定义(avee b=max{a,b})

    • (oplus)

    (k)进制下,定义(aoplus b=(a+b)mod k)

    因为(wedge,vee)不是很常用,所以这里着重介绍一下(oplus)

    我们要考虑如何构造(c(i,j)),我们发现我们需要满足:

    [c(i,j)c(i,k)=c(i,(j+k)mod k) ]

    我们在脑中想一下,诶,似乎单位根满足这个条件诶!

    于是,我们可以构造矩阵:

    [egin{bmatrix}1&1&1&cdots &1\1&w_k^1&w_k^2&cdots&w_k^{k-1}\ 1&w_k^2&w_k^4&cdots&w_k^{2(k-1)} \ vdots&vdots& vdots&ddots &vdots\ 1&w_k^{k-1}&w_k^{2(k-1)}&cdots&w_k^{(k-1)(k-1)}end{bmatrix} ]

    而它的逆矩阵就是:

    [frac{1}{k}egin{bmatrix}1&1&1&cdots &1\1&w_k^{-1}&w_k^{-2}&cdots&w_k^{-(k-1)}\ 1&w_k^{-2}&w_k^{-4}&cdots&w_k^{-2(k-1)} \ vdots&vdots& vdots&ddots &vdots\ 1&w_k^{-(k-1)}&w_k^{-2(k-1)}&cdots&w_k^{-(k-1)(k-1)}end{bmatrix} ]

    一些例题

    CF1103E Radix sum+题解 link

  • 相关阅读:
    110. 平衡二叉树-前序遍历-简单
    207. 课程表-有向图判断有无环状-中等难度
    java错误集锦
    199. 二叉树的右视图-二叉树,dfs,从右往左遍历-中等难度
    114. 二叉树展开为链表-二叉树,dfs-中等难度
    236. 二叉树的最近公共祖先-中序遍历-中等难度
    Kendo ui 入门知识点
    Css样式压缩、美化、净化工具 源代码
    Linq与Lambda常用查询语法
    15个超强悍的CSS3圆盘时钟动画赏析
  • 原文地址:https://www.cnblogs.com/Dark-Romance/p/13266355.html
Copyright © 2011-2022 走看看