快速沃尔什变换

Posted ppprseter

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速沃尔什变换相关的知识,希望对你有一定的参考价值。

快速沃尔什变换

题目背景

模板题,无背景

题目描述

给定长度为(2^n)两个序列(A,B),设(C_i=sum_{joplus k=i}A_jB_k) 分别当(oplus)or,and,xor时求出(C)

输入输出格式

输入格式:

第一行一个数(n)。 第二行(2^n)个数(A_0..A_{2^n-1}) 第三行(2^n)个数(B_0..B_{2^n-1})

输出格式:

三行每行(2^n)个数,分别代表(oplus)or,and,xor(C_0..C_{2^n-1})的值(mod 998244353)

说明

(nle 17)


证明没怎么看懂,放结论了。

or

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

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

and

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

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

xor

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

[IFWT(A)=(IFWT(A_0+A_1)/2,IFWT(A_1-A_0)/2)]

背下来吧,像(FFT)那样写就好了


Code:

#include <cstdio>
const int N=(1<<17)+10;
const int mod=998244353,inv=499122177;
int A[N],B[N],a[N],b[N],n,len;
#define add(a,b) ((a+b)%mod)
#define mul(a,b) (1ll*(a)*(b)%mod)
void orfwt(int *a,int typ)
{
    for(int le=1;le<len;le<<=1)
        for(int p=0;p<len;p+=le<<1)
            for(int i=p+le;i<p+(le<<1);i++)
                if(typ) a[i]=add(a[i],a[i-le]);
                else a[i]=add(a[i],mod-a[i-le]);
}
void andfwt(int *a,int typ)
{
    for(int le=1;le<len;le<<=1)
        for(int p=0;p<len;p+=le<<1)
            for(int i=p;i<p+le;i++)
                if(typ) a[i]=add(a[i],a[i+le]);
                else a[i]=add(a[i],mod-a[i+le]);
}
void xorfwt(int *a,int typ)
{
    for(int le=1;le<len;le<<=1)
        for(int p=0;p<len;p+=le<<1)
            for(int i=p;i<p+le;i++)
            {
                int tx=a[i],ty=a[i+le];
                a[i]=add(tx,ty),a[i+le]=add(tx,mod-ty);
                if(!typ) a[i]=mul(a[i],inv),a[i+le]=mul(a[i+le],inv);
            }
}
int main()
{
    scanf("%d",&n);len=1<<n;
    for(int i=0;i<len;i++) scanf("%d",A+i);
    for(int i=0;i<len;i++) scanf("%d",B+i);
    for(int i=0;i<len;i++) a[i]=A[i],b[i]=B[i];
    orfwt(a,1),orfwt(b,1);
    for(int i=0;i<len;i++) a[i]=mul(a[i],b[i]);
    orfwt(a,0);
    for(int i=0;i<len;i++) printf("%d ",a[i]);
    puts("");

    for(int i=0;i<len;i++) a[i]=A[i],b[i]=B[i];
    andfwt(a,1),andfwt(b,1);
    for(int i=0;i<len;i++) a[i]=mul(a[i],b[i]);
    andfwt(a,0);
    for(int i=0;i<len;i++) printf("%d ",a[i]);
    puts("");

    for(int i=0;i<len;i++) a[i]=A[i],b[i]=B[i];
    xorfwt(a,1),xorfwt(b,1);
    for(int i=0;i<len;i++) a[i]=mul(a[i],b[i]);
    xorfwt(a,0);
    for(int i=0;i<len;i++) printf("%d ",a[i]);
    puts("");
    return 0;
}

2018.12.18

以上是关于快速沃尔什变换的主要内容,如果未能解决你的问题,请参考以下文章

模板快速沃尔什变换

洛谷 - P4717 模板快速莫比乌斯/沃尔什变换 (FMT/FWT)

Codeforces 662C(快速沃尔什变换 FWT)

浅谈快速沃尔什变换

快速沃尔什变换

FWT(快速沃尔什变换)