FWT(快速沃尔什变换)

本文介绍了一种在nlogn时间复杂度内进行多项式运算的方法,包括求两个多项式的与、或、异或操作。通过快速沃尔什变换(FWT),将多项式的直接运算转化为其变换后的乘法运算,再逆变换回多项式形式,实现了高效运算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作用

 

 A,B,C均为多项式。在nlogn的时间复杂度内求C=A&B,C=A|B,C=A^B;

过程

  设A经过快速沃尔什变换后为FWT(A),FWT(C)[i]=FWT(A)[i]*FWT(B)[i];再通过FWT(C)推出C;

 

模板:https://www.luogu.org/problemnew/show/P4717

#include<cstdio>
#include<iostream>
#include<ctype.h>
using namespace std;
#define ll long long
inline ll rd()
{
    ll x=0,f=1;char c=getchar();
    while(!isdigit(c)){if(c=='-')f=-f;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
const int N=(1<<17)+13,P=998244353;
int ad(int x,int y){return x+y<P?x+y:x+y-P;}
void fwto(int *a,int n)
{
    for(int i=2,l=1;i<=n;i<<=1,l<<=1)
        for(int j=1;j<=n;j+=i)
            for(int k=0;k<l;k++)
            a[j+k+l]=ad(a[j+k+l],a[j+k]);
}
void ifwto(int *a,int n)
{
    for(int i=2,l=1;i<=n;i<<=1,l<<=1)
        for(int j=1;j<=n;j+=i)
            for(int k=0;k<l;k++)
            a[j+k+l]=ad(a[j+k+l],P-a[j+k]);
}
void fwta(int *a,int n)
{
    for(int i=2,l=1;i<=n;i<<=1,l<<=1)
        for(int j=1;j<=n;j+=i)
            for(int k=0;k<l;k++)
            a[j+k]=ad(a[j+k+l],a[j+k]);
}
void ifwta(int *a,int n)
{
    for(int i=2,l=1;i<=n;i<<=1,l<<=1)
        for(int j=1;j<=n;j+=i)
            for(int k=0;k<l;k++)
            a[j+k]=ad(P-a[j+k+l],a[j+k]);
}
int ch2(int x){return x&1?(x+P)>>1:x>>1;}
int ch(ll x,ll y){return x*y<P?x*y:x*y%P;}
void fwtx(int *a,int n)
{
    for(int i=2,l=1;i<=n;i<<=1,l<<=1)
        for(int j=1;j<=n;j+=i)
            for(int k=0,t;k<l;k++)
                t=a[j+k+l],a[j+k+l]=ad(P-t,a[j+k]),a[j+k]=ad(t,a[j+k]);
}
void ifwtx(int *a,int n)
{
    for(int i=2,l=1;i<=n;i<<=1,l<<=1)
        for(int j=1;j<=n;j+=i)
            for(int k=0,t;k<l;k++)
                t=a[j+k+l],a[j+k+l]=ch2(ad(P-t,a[j+k])),a[j+k]=ch2(ad(t,a[j+k]));
}
int a[N],b[N],c[N];
int main()
{
    int n=rd();n=1<<n;
    for(int i=1;i<=n;i++) a[i]=rd();
    for(int j=1;j<=n;j++) b[j]=rd();
    fwto(a,n);fwto(b,n);for(int i=1;i<=n;i++) c[i]=ch(a[i],b[i]);
    ifwto(a,n);ifwto(b,n);ifwto(c,n);for(int i=1;i<=n;i++) printf("%d ",c[i]);printf("\n");
    fwta(a,n);fwta(b,n);for(int i=1;i<=n;i++) c[i]=ch(a[i],b[i]);
    ifwta(a,n);ifwta(b,n);ifwta(c,n);for(int i=1;i<=n;i++) printf("%d ",c[i]);printf("\n");
    fwtx(a,n);fwtx(b,n);for(int i=1;i<=n;i++) c[i]=ch(a[i],b[i]);
    ifwtx(c,n);for(int i=1;i<=n;i++) printf("%d ",c[i]); 
}

 

 

  

转载于:https://www.cnblogs.com/LWL--Figthing/p/10959602.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值