fwt学习

转载自:https://blog.csdn.net/neither_nor/article/details/60335099

FWT能干什么:

FWT可以对于两个数组a和b,求出他们的位运算卷积c,使得c[k]=对于所有的i和j 满足 i位运算j等于k sigma a[i]*b[j]

我们先讲与卷积和或卷积,最后再讲异或卷积

一个简单的问题:

先考虑一下前言中提到的问题

给定数组a,求数组b,使得b[i]=对于所有的j满足j|i==i,sigma a[j]

我们考虑按位分治,先把数组长度用0补到2的幂

先不考虑最高位,那么我们可以把长度为2^l的原数组按最高位为0和最高位为1分为两部分

递归处理这两部分,假设我们现在已经得到了对于所有最高位为0的下标求的b数组b0和对所有最高位为1的下标求的b数组b1,他们的长度均为2^(l-1)

那么我们现在考虑最高位的影响。我们把计入最高位影响之后的长度为2^l的b数组分为左右两部分,记为bn0和bn1,即最高位为0的部分和最高位为1的部分,他们的长度也都为2^(l-1)

那么对于任意的i和j,如果j|i不等于i,给i和j添加一个最高位之后的j|i一定也不等于i,所以bn0[i]和bn1[i]只与b0[i]和b1[i]有关

而如果j|i等于i,那么假设给i添加最高位ih,给j添加最高位jh,添加最高位后j|i是否等于i就只与jh|ih是否等于ih有关

那么我们显然就可以得到bn0[i]=b0[i],bn1[i]=b0[i]+b1[i]

觉得不显然可以YY一下

如果是要求使得b[i]=对于所有的j满足j&i==i,sigma a[j]的话,那么就是bn0[0]=b0[i]+b1[i],bn1[i]=b1[i]

这样的话我们就可以在n log n的时间内求出b数组

我们会发现这个做法事实上就是或卷积的正变换

在后面我们也将求b数组叫做正变换

或卷积、与卷积的原理:

或卷积和与卷积事实上基于如下原理:

i&k==k并且j&k==k等价于(i&j)&k==k

i|k==k并且j|k==k等价于(i|j)|k==k

那么如果要求数组a和数组b的与卷积或者或卷积,我们就只需要求出a的正变换a'和b的正变换b',然后另c'[i]=a'[i]*b'[i],那么容易发现c'就是a和b的卷积做正变换的结果

那么我们现在就只需要考虑给你一个正变换之后的结果,如何做逆变换求出原数组

逆变换:

逆变换的过程事实上就是一个解密的过程,而正变换相当于加密

我们还是按位考虑,在正变换的时候,我们令bn0[i]=b0[i],bn1[i]=b0[i]+b1[i],那么如果你现在知道的是bn0和bn1,那么容易知道b0[i]=bn0[i],b1[i]=bn1[i]-bn0[i]

与运算的逆变换同理

然后再递归左右两边即可

你可能会产生疑惑:在进行正变换的时候我们先递归左右两边再考虑这一位,那么在逆变换的时候是否需要先考虑这一位再递归两边呢

而事实上因为每一位都是等价的,所以逆变换的时候一样可以先递归再考虑这一位,顺序无所谓

异或卷积:

异或这个东西和与还有或就不太一样……所以我们YY了挺长时间才YY明白异或卷积是个什么鬼畜

异或卷积基于如下原理:

定义i和j之间的奇偶性为:i&j中为1的位数的奇偶性,若为偶数则奇偶性是0,若为奇数则奇偶性是1

那么i和k的奇偶性异或j和k的奇偶性等于i^j和k的奇偶性

证明显然,YY一下即可

那么我们令数组a做正变换之后的数组b的意义是:b[i]=(sigma j满足i和j的奇偶性==0 a[j] )-(sigma j满足i和j的奇偶性==1 a[j])

那么如果要求a和b的异或卷积c,另a做完正变换为a',b做完正变换为b',c'[i]=a'[i]*b'[i],那么c'恰好就是c做正变换之后的结果

证明显然,如果觉得不显然可以稍微YY一下就明白了

那么就考虑一下如何做正变换和逆变换就好了,还是按位分治

在正变换的时候,令bn0[i]=b0[i]+b1[i],bn1[i]=b0[i]-b1[i]

在逆变换的时候,令b0[i]=(bn0[i]+bn1[i])/2,b1[i]=(bn0[i]-bn1[i])/2

正确性显然

猜你喜欢

转载自blog.csdn.net/qq_25576697/article/details/81590474
FWT