zoukankan      html  css  js  c++  java
  • 快速沃尔什变换FWT

    快速沃尔什变换(FWT)

    是一种可以快速完成集合卷积的算法。

    什么是集合卷积啊?

    集合卷积就是在集合运算下的卷积。比如一般而言我们算的卷积都是(C_i=sum_{j+k=i}A_j*B_k),而集合卷积计算的就是(C_i=sum_{jotimes k=i}A_j*B_k),其中(otimes)是一种集合运算,可以是与、或、异或。

    类似于快速傅里叶变换(FFT)(FWT)也需要寻求一种变换方式(FWT(A)),使(FWT(C)=FWT(A)*FWT(B)),其中(*)运算就是数组对应下标相乘,时间复杂度是(O(n))的。

    或(or)运算的FWT

    构造(FWT(A)=A'),其中(A'[i]=sum_{jsubseteq i}A[j])
    这样就能满足(C'=A'*B')了。
    如何构造?
    考虑把(A)分成前后两段(A_0,A_1),假设(A)的长度为(2^k)
    那么(A_0)对应的二进制中第(k-1)位一定是(0)(A_1)对应的二进制中第(k-1)位一定是(1)
    所以(FWT(A)=merge(FWT(A_0),FWT(A_1)+FWT(A_0))),其中(merge)的意思是把前后两段拼接起来,因为前后两段的长度都是(2^{k-1})

    至于(IFWT?)
    倒推一下就好了。(IFWT(A')=merge(IFWT(A'_0),IFWT(A'_1)-IFWT(A'_0)))
    代码:

    void fwt_or(ll *P,int len,int opt){
    	for (int i=1;i<len;i<<=1)
    		for (int p=i<<1,j=0;j<len;j+=p)
    			for (int k=0;k<i;++k)
    				P[j+k+i]+=P[j+k]*opt;
    }
    

    与(and)运算的FWT

    与或同理。
    构造(FWT(A)=A')(A'[i]=sum_{isubseteq j}A[j])
    (FWT(A)=merge(FWT(A_0)+FWT(A_1),FWT(A_1)))
    (IFWT(A')=merge(IFWT(A'_0)-IFWT(A'_1),IFWT(A'_1)))

    代码:

    void fwt_and(ll *P,int len,int opt){
    	for (int i=1;i<len;i<<=1)
    		for (int p=i<<1,j=0;j<len;j+=p)
    			for (int k=0;k<i;++k)
    				P[j+k]+=P[j+k+i]*opt;
    }
    

    异或(xor)运算的FWT

    直接上结论吧。
    (FWT(A)=merge(FWT(A_0)+FWT(A_1),FWT(A_0)-FWT(A_1)))
    (IFWT(A)=merge(frac{IFWT(A'_0)+IFWT(A'_1)}{2},frac{IFWT(A'_0)-IFWT(A'_1)}{2}))
    证明出门右转
    代码:

    void fwt(int *P,int len,int opt){
    	for (int i=1;i<len;i<<=1)
    		for (int p=i<<1,j=0;j<len;j+=p)
    			for (int k=0;k<i;++k)
    			{
    				int x=P[j+k],y=P[j+k+i];
    				P[j+k]=1ll*opt*(x+y)%mod;
    				P[j+k+i]=1ll*opt*(x-y+mod)%mod;
    			}
    }
    

    如果是(IFWT)的话就让(opt=frac{mod+1}2)就好了。

  • 相关阅读:
    [翻译]Kafka Streams简介: 让流处理变得更简单
    KafkaClient接口与Kafka处理请求的若干特性
    KIP-32 Add timestamps to Kafka message
    (翻译)Google Guava Cache
    Kerberos的组件和术语(翻译和注解)
    目录
    java map 分析
    编译原理
    Java中的SPI(Service Provider Interface)
    新型数据库Kudu应用经验分享
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/9067986.html
Copyright © 2011-2022 走看看