zoukankan      html  css  js  c++  java
  • [学习笔记]FWT——快速沃尔什变换

    解决涉及子集配凑的卷积问题

    一、介绍

    1.基本用法

    FWT快速沃尔什变换学习笔记

    就是解决一类问题:

    $f[k]=sum_{ioplus j=k}a[i]*b[j]$

    基本思想和FFT类似。

    首先转化成为另一个多项式$FWT(A),FWT(B)$

    使得:$FWT(Aoplus B)=FWT(A)×FWT(B)$

    这里,$×$是按位乘。这个是$O(n)$的。

    然后,再$IFWT$回去即可。

    类似于,直接过马路不好走。先从左边走上一座天桥,再从天桥走过去,再到马路右侧走下天桥。

    就变成了$O(nlogn)$

    $FWT$虽然不是非常容易理解,但是比较容易记忆。

    (虽然一定要理解)

    类比$FFT$的写法,就可以比较轻松记忆。

    就是分治压缩、合并、分治解压的过程。

    【模板】快速沃尔什变换

    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC optimize("Ofast")
    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define numb (ch^'0')
    using namespace std;
    typedef long long ll;
    il void rd(int &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    il void prin(int x){
        if(x/10) prin(x/10);
        putchar(x%10+'0');
    }
    namespace Miracle{
    const int N=131072+4;
    const int mod=998244353;
    const int inv2=499122177;
    int a[N],b[N];
    int c[N],d[N];
    int e[N];
    int n;
    void _or(int *f,int op){
        for(reg p=2;p<=n;p<<=1){
            int len=p/2;    
            for(reg k=0;k<n;k+=p){
                for(reg l=k;l<k+len;++l){
                    if(op==1)f[l+len]=(f[l+len]+f[l])%mod;    
                    else f[l+len]=(f[l+len]-f[l]+mod)%mod;
                }
            }
        }
    }
    void _and(int *f,int op){
        for(reg p=2;p<=n;p<<=1){
            int len=p/2;    
            for(reg k=0;k<n;k+=p){
                for(reg l=k;l<k+len;++l){
                    if(op==1)f[l]=(f[l+len]+f[l])%mod;    
                    else f[l]=(f[l]-f[l+len]+mod)%mod;
                }
            }
        }
    }
    void _xor(int *f,int op){
        for(reg p=2;p<=n;p<<=1){
            int len=p/2;    
            for(reg k=0;k<n;k+=p){
                for(reg l=k;l<k+len;++l){
                    int x=f[l],y=f[l+len];
                    if(op==1){
                        f[l]=(x+y)%mod;
                        f[l+len]=(x-y+mod)%mod;
                    }
                    else{
                        f[l]=(ll)(x+y)*inv2%mod;
                        f[l+len]=(ll)(x-y+mod)%mod*inv2%mod;
                    }
                }
            }
        }
    }
    int main(){
        scanf("%d",&n);
        n=(1<<n);
        for(reg i=0;i<n;++i) rd(a[i]),c[i]=a[i];
        for(reg i=0;i<n;++i) rd(b[i]),d[i]=b[i];
        
        _or(c,1);_or(d,1);
        for(reg i=0;i<n;++i) e[i]=(ll)c[i]*d[i]%mod;
        _or(e,-1);
        for(reg i=0;i<n;++i){
            prin(e[i]);putchar(' ');c[i]=a[i],d[i]=b[i];
        }putchar('
    ');
        
        _and(c,1);_and(d,1);
        for(reg i=0;i<n;++i) e[i]=(ll)c[i]*d[i]%mod;
        _and(e,-1);
        for(reg i=0;i<n;++i){
            prin(e[i]);putchar(' ');c[i]=a[i],d[i]=b[i];
        }putchar('
    ');
        
        _xor(c,1);_xor(d,1);
        for(reg i=0;i<n;++i) e[i]=(ll)c[i]*d[i]%mod;
        _xor(e,-1);
        for(reg i=0;i<n;++i){
            prin(e[i]);putchar(' ');//c[i]=a[i],d[i]=b[i];
        }putchar('
    ');
        return 0;
    }
    
    }
    int main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2018/11/22 15:08:15
    */
    模板

    2.子集卷积

    https://www.cnblogs.com/Dance-Of-Faith/p/8818211.html

     多加一维i,强制记录涉及集合sz大小

    外层枚举sz

    O(2^n*n^2)

    (推荐使用FWT,因为比FMT常数小)

    二、例题

    留坑

     安师大附中集训 Day2

    [FWT] UOJ #310. 【UNR #2】黎明前的巧克力

    三、FFT、NTT、FWT的比较

    留坑

    没啥可比较的。处理思路一致。

    就是运算符的问题吧。

    四、FWT、FMT的比较

    留坑

     FMT好写,FWT的与或卷积的第一步可以取代FMT


    upda:2019.4.17

    FMT可以代替FWT的与或卷积。IFMT把+改成-即可

    (xor暂时不知道具体含义,估计也可以代替?)

    实际上

    FMT很辣鸡

    相比之下,FWT做的事情完全包含FMT,并且常数是FMT的1/2!

    [WC2018]州区划分(这个题我人傻常数大,必须用FWT卡常才能过)

    所以还是写FWT吧

  • 相关阅读:
    [Unity菜鸟] 摄像头
    [Unity菜鸟] Final IK
    谷歌 值得关注的网站
    [Unity菜鸟] 射线
    [Unity菜鸟] Character控制移动
    [Unity菜鸟] FBX模型动画提取
    [Unity菜鸟] Time
    [Unity菜鸟] 产生各不相同的随机数
    [Unity菜鸟] 材质
    反调试:检测进程名
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10001498.html
Copyright © 2011-2022 走看看