Luo Gu P4717 [template] Fast Walsh Transform (fmt && fwt)

Copyright: Oh ...... but still free to reprint please indicate the source of it: https://blog.csdn.net/dreaming__ldx/article/details/89041894

Portal
Template title = = == Water template
for O r or be used f m t fmt , with the remaining two kinds of f w t fwt like.
Of course, you can consider using divide and conquer multiplication.
Code:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
    static char buf[rlen],*ib,*ob;
    (ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
    return ib==ob?-1:*ib++;
}
inline int read(){
    int ans=0;
    char ch=gc();
    while(!isdigit(ch))ch=gc();
    while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
    return ans;
}
typedef long long ll;
const int mod=998244353;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline void update(int&a,const int&b){a=a+b>=mod?a+b-mod:a+b;}
int n,lim;
vector<int>a,b,c;
inline vector<int> solve(int up){
    if(!up)return vector<int>(1,mul(a[0],b[0]));
    int mid=up>>1;
    vector<int> ret,tmp;
    ret=solve(mid);
    for(ri i=mid+1;i<=up;++i)update(a[i-mid-1],a[i]),update(b[i-mid-1],b[i]);
    tmp=solve(mid);
    puts("------");
    for(ri i=0;i<=mid;++i)cerr<<ret[i]<<' ';
    puts("");
    for(ri i=0;i<=mid;++i)cerr<<tmp[i]<<' ';
    puts("");
    for(ri i=mid+1;i<=up;++i)a[i-mid-1]=dec(a[i-mid-1],a[i]),b[i-mid-1]=dec(b[i-mid-1],b[i]);
    for(ri i=0;i<=mid;++i)ret.push_back(dec(tmp[i],ret[i]));
    for(ri i=0;i<=up;++i)cerr<<ret[i]<<' ';
    puts("");
    puts("------");
    return ret;
}
inline void fmt(vector<int>&a,const int&type){
    for(ri mid=1;mid<lim;mid<<=1)for(ri i=0;i<lim;++i)
    if(i&mid)a[i]=~type?add(a[i],a[i^mid]):dec(a[i],a[i^mid]);
}
inline void fwt_and(vector<int>&a,const int&type){
    for(ri mid=1;mid<lim;mid<<=1)for(ri j=0,len=mid<<1;j<lim;j+=len)
    for(ri k=0;k<mid;++k)a[j+k]=~type?add(a[j+k],a[j+k+mid]):dec(a[j+k],a[j+k+mid]);
}
inline void fwt_xor(vector<int>&a,const int&type){
    int a0,a1,inv=(mod+1)/2;
    for(ri mid=1;mid<lim;mid<<=1)for(ri j=0,len=mid<<1;j<lim;j+=len)
    for(ri k=0;k<mid;++k){
        a0=a[j+k],a1=a[j+k+mid];
        a[j+k]=add(a0,a1),a[j+k+mid]=dec(a0,a1);
        if(type==-1)a[j+k]=mul(a[j+k],inv),a[j+k+mid]=mul(a[j+k+mid],inv);
    }
}
int main(){
    n=read(),lim=1<<n;
    for(ri i=0;i<lim;++i)a.push_back(read());
    for(ri i=0;i<lim;++i)b.push_back(read());
    c.resize(lim);
    fmt(a,1),fmt(b,1);
    for(ri i=0;i<lim;++i)c[i]=mul(a[i],b[i]);
    fmt(c,-1),fmt(a,-1),fmt(b,-1);
    for(ri i=0;i<lim;++i)cout<<c[i]<<' ';
    puts("");
    fwt_and(a,1),fwt_and(b,1);
    for(ri i=0;i<lim;++i)c[i]=mul(a[i],b[i]);
    fwt_and(c,-1),fwt_and(a,-1),fwt_and(b,-1);
    for(ri i=0;i<lim;++i)cout<<c[i]<<' ';
    puts("");
    fwt_xor(a,1),fwt_xor(b,1);
    for(ri i=0;i<lim;++i)c[i]=mul(a[i],b[i]);
    fwt_xor(c,-1);
    for(ri i=0;i<lim;++i)cout<<c[i]<<' ';
    puts("");
    return 0;
}

Guess you like

Origin blog.csdn.net/dreaming__ldx/article/details/89041894