fwt主要是用来处理一类卷积问题的

首先说明一下集合幂级数

这就是一个用集合作为下标的函数

而fwt可以处理一类与集合幂级数相关的卷积问题

我们考虑是一个关于集合的运算

现在有集合

我们需要求

其中是任意运算

如何处理这个问题

我们如果能构造出一种对于的变换,使得

(指对应位置运算,而不是卷积)

那么就可以对变换,在算出后变换回来,得到答案

那么问题在于如何得到这种变换

我们考虑最高位的情况

我们定义为最高位为的变换结果,为最高位为的变换结果

现在如果可以用表示,那问题就能解决

接下来我们对不同的运算具体分析

这里我们先定义()指直接将相接,后面会用到

xor

对于xor运算,我们可以发现

这里有个结论

推我不会,但证明应该谁都会

同理逆变换

代码

1
2
3
4
5
6
7
8
9
10
11
12
void txor(lg *a,int n,int on=1){
int U=1<<n;
for(int i=2,p=1;i<=U;i<<=1,p<<=1){
for(int j=0;j<U;j+=i){
for(int k=j;k<j+p;++k){
lg A=a[k],B=a[k+p];
a[k]=(A+B)*on%Md;a[k+p]=(A-B)*on%Md;
if(a[k+p]<0)a[k+p]+=Md;
}
}
}
}

and

还是背结论吧

代码

1
2
3
4
5
6
7
8
9
10
11
void tand(lg *a,int n,int on=1){
int U=1<<n;
for(int i=2,p=1;i<=U;i<<=1,p<<=1){
for(int j=0;j<U;j+=i){
for(int k=j;k<j+p;++k){
a[k]=(a[k]+a[k+p]*on)%Md;
if(a[k]<0)a[k]+=Md;
}
}
}
}

or

代码

1
2
3
4
5
6
7
8
9
10
11
void tor(lg *a,int n,int on=1){
int U=1<<n;
for(int i=2,p=1;i<=U;i<<=1,p<<=1){
for(int j=0;j<U;j+=i){
for(int k=j;k<j+p;++k){
a[k+p]=(a[k+p]+a[k]*on)%Md;
if(a[k+p]<0)a[k+p]+=Md;
}
}
}
}

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
namespace Ura{
void txor(lg *a,int n,int on=1){
int U=1<<n;
for(int i=2,p=1;i<=U;i<<=1,p<<=1){
for(int j=0;j<U;j+=i){
for(int k=j;k<j+p;++k){
lg A=a[k],B=a[k+p];
a[k]=(A+B)*on%Md;a[k+p]=(A-B)*on%Md;
if(a[k+p]<0)a[k+p]+=Md;
}
}
}
}
void tand(lg *a,int n,int on=1){
int U=1<<n;
for(int i=2,p=1;i<=U;i<<=1,p<<=1){
for(int j=0;j<U;j+=i){
for(int k=j;k<j+p;++k){
a[k]=(a[k]+a[k+p]*on)%Md;
if(a[k]<0)a[k]+=Md;
}
}
}
}
void tor(lg *a,int n,int on=1){
int U=1<<n;
for(int i=2,p=1;i<=U;i<<=1,p<<=1){
for(int j=0;j<U;j+=i){
for(int k=j;k<j+p;++k){
a[k+p]=(a[k+p]+a[k]*on)%Md;
if(a[k+p]<0)a[k+p]+=Md;
}
}
}
}
}

最后更新: 2019年01月14日 18:47

原始链接: http://tenecnt.github.io/2018/09/20/fwt/