zoukankan      html  css  js  c++  java
  • 能轻松背板子的FWT(快速沃尔什变换)

    FWT应用

    我不知道(FWT)的严格定义
    百度百科和维基都不知道给一坨什么**东西

    FWT(Fast Walsh Fransform),中文名快速沃尔什变换
    然后我也不知道(FWT)到底是什么
    你们怎么念FWT的反正我念扶卧塔

    (FFT)当然可以做多项式卷积
    形如(C(k)=sum_{i+j=k}f[i]g[j]),很简单,大家都会
    由于有这个性质所以也可做分治(FFT)

    但是如果把(i+j)换一下操作符
    变成(C(k)=sum_{i???j=k}f[i]g[j])
    其中(???)可以是(or,and,xor)三种运算
    这时就要用(FWT)来做特殊卷积了


    结论

    类似(FFT),把当前多项式(A)拆成前一半(A_0)和后一半(A_1)
    注意不是奇数项和偶数项,只是前一半和后一半……(狗头保命)
    也可知(FWT)也只能处理长度为(2)的次幂的多项式

    or

    [FWT(A)=merge(FWT(A_0),FWT(A_0)+FWT(A_1)) ]

    [IFWT(A)=merge(IFWT(A_0),IFWT(A_0)-IFWT(A_1)) ]

    and

    [FWT(A)=merge(FWT(A_0)+FWT(A_1),FWT(A_1)) ]

    [IFWT(A)=merge(IFWT(A_0)-IFWT(A_1),IFWT(A_1)) ]

    xor

    [FWT(A)=merge(FWT(A_0)+FWT(A_1),FWT(A_0)-FWT(A_1)) ]

    [IFWT(A)=merge({{IFWT(A_0)+IWFT(A_1)}over 2},{IFWT(A_0)-IFWT(A_1)over 2}) ]

    (+)就是每一位值加起来,不知道(merge)是什么东西?
    其实就是两个多项式前后拼起来……(狗头保命)
    所以就算不清楚原理背下结论也很容易写出板子
    由于某些原因原理完全可以跳过不看
    但还是懂一下比较好


    原理

    清真のor&and

    (FWT(A)=A',A'[i]=sum_{i|j=i}A[j])(B)同理
    (i|j=i)就表示二进制下(j)一定是(i)的子集
    这样好像可以满足(C'[i]=A'[i]*B'[i]),不懂可以写一写
    大概就是(A'[i])已经包含下标或起来(=i)(A)(B'[i])也是
    所以(A'[i],B'[i])里包含的每个数下标或起来都等于(i)
    自然两个和乘起来就是两两配对的总和,即(C'[i]=A'[i]*B'[i])

    肯定不能枚举(i)的二进制子集因为太沙雕
    然后试着把(A)拆成前半段(A_0)和后半段(A_1)
    如果知道(FWT(A_0),FWT(A_1)),可以知道(FWT(A))
    是个学过FFT的人都知道应该可以

    设当前多项式(A)的长度为(2^k)(A_0,A_1)长度为(2^{k-1})
    (FWT(A))的前半段表示(A)的二进制位第(k)位填(0)
    那么是它子集的好像(FWT(A_0))
    (FWT(A))的前半段表示(A)的二进制位第(k)位填(1)
    是它子集的不仅有(FWT(A_1)),还有(FWT(A_0))
    大概就是这个亚子其实我也不是很清楚
    所以(FWT(A))前半段就是(FWT(A_0)),后半段就是(FWT(A_0),FWT(A_1))加起来
    于是就有了结论的(FWT(A)=merge(FWT(A_0),FWT(A_0)+FWT(A_1)))

    至于(IFWT),就是已知(A_0',A_1'),求(A_0,A_1)
    由于(A_0'=A_0,A_1'=A_0+A_1),所以(A_0=A_0',A_1=A_1'-A_0')
    这样就有了两个简单易懂易背的结论

    对于(and)也可同理推一波操作,和(or)很像,结论、代码也很像
    打对(or)就可以打对(and).jpg

    鬼畜のxor

    一看(or)(and)的结论就很清真,其实是因为(or)(and)很像
    (xor)奇怪就奇怪在运算和(or,and)有很大区别
    (xor)卷积还是有优化的方法

    (i&j)(1)数量的奇偶性为(i)(j)的奇偶性,那么(i)(k)的奇偶性异或(j)(k)的奇偶性等于(i⊕j)(k)的奇偶性
    (f(x))表示(x)在二进制下(1)的个数

    [A'[i]=sum_{f(i&j)mod2=0}A[j]-sum_{f(i&j)mod2=1}A[j] ]

    如果这样的话

    [FWT(A)=merge(FWT(A_1)-FWT(A_0),FWT(A_1)+FWT(A_0)) ]

    [IFWT(A)=merge({{IFWT(A_1)-IWFT(A_0)}over 2},{IFWT(A_1)+IFWT(A_0)over 2}) ]

    对于(or),由于(or,and)同理,令

    [A'[i]=sum_{f(i|j)mod2=0}A[j]-sum_{f(i|j)mod2=1}A[j] ]

    结果和上面的是一样的
    于是由这两种运算的优美性质自然而然的可以得到xor的规律
    于是你就知道为什么xor那么鬼畜


    FWT板子

    #define mod 998244353 
    #define inv2 499122177
    inline void fwt_or(ll f[],ll len,ll inv)
    {
    	for (ll i=1;i<len;i<<=1)
    		for (ll j=0;j<len;j+=(i<<1))
    			for (ll k=0;k<i;++k)
    				f[i+j+k]=(inv*f[j+k]+f[i+j+k]+mod)%mod;
    }
    inline void fwt_and(ll f[],ll len,ll inv)
    {
    	for (ll i=1;i<len;i<<=1)
    		for (ll j=0;j<len;j+=(i<<1))
    			for (ll k=0;k<i;++k)
    				f[j+k]=(f[j+k]+inv*f[i+j+k]+mod)%mod;
    }
    inline void fwt_xor(ll f[],ll len,ll inv)
    {
    	for (ll i=1;i<len;i<<=1)
    		for (ll j=0;j<len;j+=(i<<1))
    			for (ll k=0;k<i;++k)
    			{
    				ll x=f[j+k],y=f[i+j+k];
    				f[j+k]=(x+y)%mod,f[i+j+k]=(x-y+mod)%mod;
    				if (inv==-1)(f[j+k]*=inv2)%=mod,(f[i+j+k]*=inv2)%=mod;
    			}
    }
    

    FWT搞完

    本人版权意识薄弱……

    别人早就会的东西我现在才学
    (FFT)都会了一年了我才懂(FWT)
    原因还是我太蔡了

  • 相关阅读:
    关于jsp页面是放在webroot目录下和web-inf下优缺点
    eclipse查看jar包中class的中文注释乱码问题的解决
    如何在eclipse里使用git
    ****JFinal 部署在 Tomcat 下推荐方法
    jfinal框架教程-学习笔记(二)
    Struts2 标签库讲解
    struts2 标签库 介绍
    VC无闪烁刷屏技术的实现【转】
    小知识:SPI四种模式区别【转】
    如何在Android 或Linux 下,做Suspend /Resume 的Debug【转】
  • 原文地址:https://www.cnblogs.com/horizonwd/p/11478230.html
Copyright © 2011-2022 走看看