快速沃尔什变换
题目背景
模板题,无背景
题目描述
给定长度为\(2^n\)两个序列\(A,B\),设\(C_i=\sum_{j\oplus 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}\)的值\(\bmod\ 998244353\)
说明
\(n\le 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
原文地址:https://www.cnblogs.com/ppprseter/p/10136407.html
时间: 2024-10-07 05:07:26