加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

能轻松背板子的FWT(快速沃尔什变换)

发布时间:2020-12-15 07:51:00 所属栏目:Java 来源:网络整理
导读:FWT应用 我不知道 (FWT) 的严格定义 百度百科和维基都不知道给一坨什么 ****东西** FWT(Fast Walsh Fransform) ,中文名 快速沃尔什变换 然后我也不知道 (FWT) 到底是什么 你们怎么念FWT的反正我念扶卧塔 (FFT) 当然可以做多项式卷积 形如 (C(k)=s

FWT应用

我不知道(FWT)的严格定义
百度百科和维基都不知道给一坨什么****东西**

FWT(Fast Walsh Fransform),中文名快速沃尔什变换
然后我也不知道(FWT)到底是什么
你们怎么念FWT的反正我念扶卧塔

(FFT)当然可以做多项式卷积
形如(C(k)=sum_{i+j=k}f[i]g[j]),很简单,大家都会
由于有这个性质所以也可做分治(FFT)

但是如果把(i+j)换一下操作符
变成(C(k)=sum_{i???j=k}f[i]g[j])
其中(???)可以是(or,and,xor)三种运算
这时就要用(FWT)来做特殊卷积了


结论

类似(FFT),把当前多项式(A)拆成前一半(A_0)和后一半(A_1)
注意不是奇数项和偶数项,只是前一半和后一半……(狗头保命)
也可知(FWT)也只能处理长度为(2)的次幂的多项式

or

[FWT(A)=merge(FWT(A_0),FWT(A_0)+FWT(A_1))]

[IFWT(A)=merge(IFWT(A_0),IFWT(A_0)-IFWT(A_1))]

and

[FWT(A)=merge(FWT(A_0)+FWT(A_1),FWT(A_1))]

[IFWT(A)=merge(IFWT(A_0)-IFWT(A_1),IFWT(A_1))]

xor

[FWT(A)=merge(FWT(A_0)+FWT(A_1),FWT(A_0)-FWT(A_1))]

[IFWT(A)=merge({{IFWT(A_0)+IWFT(A_1)}over 2},{IFWT(A_0)-IFWT(A_1)over 2})]

(+)就是每一位值加起来,不知道(merge)是什么东西?
其实就是两个多项式前后拼起来……(狗头保命)
所以就算不清楚原理背下结论也很容易写出板子
由于某些原因原理完全可以跳过不看
但还是懂一下比较好


原理

清真のor&and

(FWT(A)=A',A'[i]=sum_{i|j=i}A[j])(B)同理
(i|j=i)就表示二进制下(j)一定是(i)的子集
这样好像可以满足(C'[i]=A'[i]*B'[i]),不懂可以写一写
大概就是(A'[i])已经包含下标或起来(=i)(A)(B'[i])也是
所以(A'[i],B'[i])里包含的每个数下标或起来都等于(i)
自然两个和乘起来就是两两配对的总和,即(C'[i]=A'[i]*B'[i])

肯定不能枚举(i)的二进制子集因为太沙雕
然后试着把(A)拆成前半段(A_0)和后半段(A_1)
如果知道(FWT(A_0),FWT(A_1)),可以知道(FWT(A))
是个学过FFT的人都知道应该可以

设当前多项式(A)的长度为(2^k)(A_0,A_1)长度为(2^{k-1})
(FWT(A))的前半段表示(A)的二进制位第(k)位填(0)
那么是它子集的好像(FWT(A_0))
(FWT(A))的前半段表示(A)的二进制位第(k)位填(1)
是它子集的不仅有(FWT(A_1)),还有(FWT(A_0))
大概就是这个亚子其实我也不是很清楚
所以(FWT(A))前半段就是(FWT(A_0)),后半段就是(FWT(A_0),FWT(A_1))加起来
于是就有了结论的(FWT(A)=merge(FWT(A_0),FWT(A_0)+FWT(A_1)))

至于(IFWT),就是已知(A_0',A_1'),求(A_0,A_1)
由于(A_0'=A_0,A_1'=A_0+A_1),所以(A_0=A_0',A_1=A_1'-A_0')
这样就有了两个简单易懂易背的结论

对于(and)也可同理推一波操作,和(or)很像,结论、代码也很像
打对(or)就可以打对(and).jpg

鬼畜のxor

一看(or)(and)的结论就很清真,其实是因为(or)(and)很像
(xor)奇怪就奇怪在运算和(or,and)有很大区别
(xor)卷积还是有优化的方法

(i&;j)(1)数量的奇偶性为(i)(j)的奇偶性,那么(i)(k)的奇偶性异或(j)(k)的奇偶性等于(i⊕j)(k)的奇偶性
(f(x))表示(x)在二进制下(1)的个数
[A'[i]=sum_{f(i&;j)mod2=0}A[j]-sum_{f(i&;j)mod2=1}A[j]]

如果这样的话
[FWT(A)=merge(FWT(A_1)-FWT(A_0),FWT(A_1)+FWT(A_0))]

[IFWT(A)=merge({{IFWT(A_1)-IWFT(A_0)}over 2},{IFWT(A_1)+IFWT(A_0)over 2})]
对于(or),由于(or,and)同理,令
[A'[i]=sum_{f(i|j)mod2=0}A[j]-sum_{f(i|j)mod2=1}A[j]]
结果和上面的是一样的
于是由这两种运算的优美性质自然而然的可以得到xor的规律
于是你就知道为什么xor那么鬼畜


FWT板子

#define mod 998244353 
#define inv2 499122177
inline void fwt_or(ll f[],ll len,ll inv)
{
    for (ll i=1;i<len;i<<=1)
        for (ll j=0;j<len;j+=(i<<1))
            for (ll k=0;k<i;++k)
                f[i+j+k]=(inv*f[j+k]+f[i+j+k]+mod)%mod;
}
inline void fwt_and(ll f[],ll inv)
{
    for (ll i=1;i<len;i<<=1)
        for (ll j=0;j<len;j+=(i<<1))
            for (ll k=0;k<i;++k)
                f[j+k]=(f[j+k]+inv*f[i+j+k]+mod)%mod;
}
inline void fwt_xor(ll f[],ll inv)
{
    for (ll i=1;i<len;i<<=1)
        for (ll j=0;j<len;j+=(i<<1))
            for (ll k=0;k<i;++k)
            {
                ll x=f[j+k],y=f[i+j+k];
                f[j+k]=(x+y)%mod,f[i+j+k]=(x-y+mod)%mod;
                if (inv==-1)(f[j+k]*=inv2)%=mod,(f[i+j+k]*=inv2)%=mod;
            }
}

FWT搞完

本人版权意识薄弱……

  • 本博客部分知识学习于
  • https://blog.csdn.net/qq_37136305/article/details/81606170
  • https://www.cnblogs.com/ACMLCZH/p/8022502.html
  • https://blog.csdn.net/gmh77/article/details/82320090
  • https://blog.csdn.net/zsyz_ZZY/article/details/89881380

别人早就会的东西我现在才学
(FFT)都会了一年了我才懂(FWT)
原因还是我太蔡了

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读