FWT学习笔记& P4717 【模板】快速沃尔什变换

背景:

好像要回去备战听说了。
. . . ...

题目传送门:

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

正题:

我们的 FFT \text{FFT} 可以解决一类这样的问题: C i = j + k = i A j B k C_i=\sum_{j+k=i}A_j·B_k
有的时候,问题可以变成这样: C i = j k = i A j B k C_i=\sum_{j⊕k=i}A_j·B_k ,其中的 指的是 or,xor,and \text{or,xor,and} 中的一种。
那又该怎么办呢?

那就要用到 FWT \text{FWT} 了。
类似 FFT \text{FFT} ,你构造一个 FWT \text{FWT} IFWT \text{IFWT} ,对于不同的情况分开来处理即可。

结论:

or \text{or}
t f ( A ) = ( t f ( A 0 ) , t f ( A 1 ) + t f ( A 0 ) ) tf(A)=(tf(A0),tf(A1)+tf(A0))
u t f ( A ) = ( u t f ( A 0 ) , u t f ( A 1 ) u t f ( A 0 ) ) utf(A)=(utf(A0),utf(A1)−utf(A0))

xor \text{xor}
t f ( A ) = ( t f ( A 0 ) + t f ( A 1 ) , t f ( A 0 ) t f ( A 1 ) ) tf(A)=(tf(A0)+tf(A1),tf(A0)−tf(A1))
u t f ( A ) = ( u t f ( A 0 + A 1 ) 2 , u t f ( A 0 A 1 ) 2 ) utf(A)=(\frac{utf(A0+A1)}{2},\frac{utf(A0−A1)}{2})

and \text{and}
t f ( A ) = ( t f ( A 0 ) + t f ( A 1 ) , t f ( A 1 ) ) tf(A)=(tf(A0)+tf(A1),tf(A1))
u t f ( A ) = ( u t f ( A 0 ) u t f ( A 1 ) , u t f ( A 1 ) ) utf(A)=(utf(A0)−utf(A1),utf(A1))

证明

详见 yyb’s blog \text{yyb's blog}
我也不会啊。
over. \text{over.}

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define mod 998244353
#define inv2 499122177
#define MAXN 1<<17
using namespace std;
	int len;
	LL a[MAXN],b[MAXN],c[MAXN];
void FWT_or(LL *f,int op)
{
	for(int i=1;i<len;i<<=1)
		for(int j=0;j<len;j+=(i<<1))
			for(int k=0;k<i;k++)
				f[i+j+k]=(f[i+j+k]+f[j+k]*op+mod)%mod;
}
void FWT_and(LL *f,int op)
{
	for(int i=1;i<len;i<<=1)
		for(int j=0;j<len;j+=(i<<1))
			for(int k=0;k<i;k++)
				f[j+k]=(f[j+k]+f[i+j+k]*op+mod)%mod;
}
void FWT_xor(LL *f,int op)
{
	for(int i=1;i<len;i<<=1)
		for(int j=0;j<len;j+=(i<<1))
			for(int k=0;k<i;k++)
			{
				int x=f[j+k],y=f[i+j+k];
				f[j+k]=(x+y)%mod;
				f[i+j+k]=(x-y+mod)%mod;
				if(op==-1)
				{
					f[j+k]=f[j+k]*inv2%mod;
					f[i+j+k]=f[i+j+k]*inv2%mod;
				}
			}
}
void work_or()
{
	FWT_or(a,1);
	FWT_or(b,1);
	for(int i=0;i<len;i++)
		c[i]=a[i]*b[i]%mod;
	FWT_or(a,-1);
	FWT_or(b,-1);
	FWT_or(c,-1);
}
void work_and()
{
	FWT_and(a,1);
	FWT_and(b,1);
	for(int i=0;i<len;i++)
		c[i]=a[i]*b[i]%mod;
	FWT_and(a,-1);
	FWT_and(b,-1);
	FWT_and(c,-1);
}
void work_xor()
{
	FWT_xor(a,1);
	FWT_xor(b,1);
	for(int i=0;i<len;i++)
		c[i]=a[i]*b[i]%mod;
	FWT_and(a,-1);
	FWT_and(b,-1);
	FWT_xor(c,-1);
}
void print()
{
	for(int i=0;i<len;i++)
		printf("%lld ",c[i]);
	printf("\n");
}
int main()
{
	scanf("%d",&len);
	len=1<<len;
	for(int i=0;i<len;i++)
		scanf("%lld",&a[i]);
	for(int i=0;i<len;i++)
		scanf("%lld",&b[i]);
	work_or(),print();
	work_and(),print();
	work_xor(),print();
}

猜你喜欢

转载自blog.csdn.net/zsyz_ZZY/article/details/89881380