博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[多项式算法](Part 4)FWT 快速沃尔什变换 学习笔记
阅读量:5109 次
发布时间:2019-06-13

本文共 3643 字,大约阅读时间需要 12 分钟。

其他多项式算法传送门:

\(4.Extreme-FWT\)

  • FWT\((Fast\ Walsh-Hadamard\ Transform)\)

    中文名称:快速沃尔什变换

    (Fast Wrong-Answer Transform)


\(Q:\)有完没完了?\(FWT\)又是什么?现在已经能处理任意情况的多项式乘法了,还要这个干什么?

\(A:\)我也不想学啊,根本背不下来

虽然现在我们可以快速求出\(C=A*B,C_k=\sum_{i+j=k}A_i*B_j\)了,但是现在让你求\(C=A\oplus B,C_k=\sum_{i\oplus j=k}A_i*B_j\),其中\(\oplus\)代表一个位运算符号,如\(|(or),\&(and),\land(xor)\),你该怎么做呢?

这时就到\(FWT\)登场了。

接下来让我们对于\(FWT\)\(3\)种形式感性理解分别讨论


\(Part1--FWT(or)\)

\(A_0,A_1\)分别表示长度为\(n=2^x\)的多项式\(A\)的前半部分和后半部分。

首先,给出\(FWT(A)\)的计算方式:

\[ FWT(A)=\begin{cases} (FWT(A_0),FWT(A_0)+FWT(A_1))&(n>1)\\ A&(n=1) \end{cases} \]

其中\((A,B)\)表示两个多项式相连。

那么\(n=1\)是显然是对的,边界嘛。

至于\(n>1\)的情况如何理解?

对于\(A_0\)\(A_0\)中两个数下标\(or\)起来一点还在\(A_0\)中(二进制下最高位为\(0\),是前半部分),那么就只对前半部分有贡献。

对于\(A_1\)\(A_1\)中两个数,同理只对后半部分有贡献。

对于\(A_0\)\(A_1\)中的两个数,思考\(FWT(A)_k\)的意义,有:

\[FWT(A)_k=\sum_{i|k=k}A_i\]

因为当\(i|k=k,j|k=k\)时,有\((i|j)|k=k\),满足\(FWT\)的可合并性质。

那么因为\(A_1\)下标二进制最高位为\(1\),所以\(or\)起来只对后半部分产生贡献。

贡献就是\(A_0\)\(A_1\)的贡献(\(A_1\)已经贡献过自己了,不用再加)。

那么式子就很明显了。

同时根据\(FWT(A)\)的意义,容易发现\(FWT(A_0+A_1)=FWT(A_0)+FWT(A_1)\)

接下来证明\(FWT(A|B)=FWT(A)*FWT(B)\)(保证\(or\)卷积答案的正确性,要不然\(FWT\)就没有用了)。

\(n=1\)时,性质显然成立

\(n>1\)时,:

\[ \begin{equation} \begin{split} FWT(A|B)=&FWT((A|B)_0,(A|B)_1)\\ &=FWT(A_0|B_0,A_0|B_1+A_1|B_0+A_1|B_1)\\ &=(FWT(A_0|B_0),FWT(A_0|B_0+A_0|B_1+A_1|B_0+A_1|B_1))\\ &=(FWT(A_0)*FWT(B_0),FWT(A_0)*FWT(B_0)+FWT(A_0)*FWT(B_1)\\ &+FWT(A_1)*FWT(B_0)+FWT(A_1)*FWT(B_1))\\ &=(FWT(A_0)*FWT(B_0),(FWT(A_0)+FWT(A_1))*(FWT(B_0)+FWT(B_1)))\\ &=(FWT(A_0)*FWT(B_0),FWT(A_0+A_1)*FWT(B_0+B_1)))\\ &=(FWT(A_0),FWT(A_0+A_1))*(FWT(B_0),FWT(B_0+B_1))\\ &=FWT(A)*FWT(B) \end{split} \end{equation} \]

由数学归纳法得知,此性质成立。

那么\(or\)\(FWT\)就很好写了~~代码在后面。

\(Part2--FWT(and)\)

\(and\)\(FWT\)就和\(or\)的很类似了。

因为\(A_0\)\(A_1\)最高位不同,那么\(and\)后只对\(A_0\)有贡献。

类似\(or\)的,可以得到\(FWT(A)\)的计算方式:

\[ FWT(A)=\begin{cases} (FWT(A_0)+FWT(A_1),FWT(A_1))&(n>0)\\ A(n=0) \end{cases} \]

至于证明就不写了,和\(or\)的类似,写着麻烦

\(Part3--FWT(xor)\)

\(xor\)来了

说实话,在网上找了许多\(Blog\),似乎都没有给出构造方法,那么我也不会啊

你就当是某位神仙找的规律吧

首先是\(FWT(A)\)的计算方式:

\[ FWT(A)=\begin{cases} (FWT(A_0)+FWT(A_1),FWT(A_0)-FWT(A_1))&(n>0)\\ A(n=0) \end{cases} \]

看着都恶心,这怎么构造出来的啊\(QAQ\)

那么根据定义,很容易证明\(FWT(A\pm B)=FWT(A)\pm FWT(B)\)

因为\(FWT\)是一个线性组合,满足以上性质。

然后是\(FWT(A\land B)=FWT(A)*FWT(B)\)

这个也可以用数学归纳法证明,详见参考资料


\(Q:\)等等……是不是少了什么?\(FWT\)后怎么变回去呢?

\(A:\)这还不简单接下来的过程就是\(IFWT\)了!

\(Part4--IFWT(or)\)

\(Emm...\)至于\(IFWT\)呢就很简单了,把变换倒过来即可。

(这不是废话吗)

那么对于\(or\)\(IFWT\),考虑之前有\(FWT\)的方程:

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

也就是:

\[FWT(A)_0=FWT(A_0),FWT(A)_1=FWT(A_0)+FWT(A_1)\]

\[FWT(A_0)=FWT(A)_0,FWT(A_1)=FWT(A_0)-FWT(A)_1=FWT(A)_0-FWT(A)_1\]

此时定义\(IFWT(A)_0=FWT(A_0),IFWT(A)_1=FWT(A_1)\) ,也就有:

\[ IFWT(A)=\begin{cases} (IFWT(A_0),IFWT(A_0)-IFWT(A_1))&(n>0)\\ A&(n=0) \end{cases} \]

\(En...\)真简单

\(Part5--IFWT(and)\)

类似\(or\)\(IFWT\),可以直接得到:

\[ IFWT(A)=\begin{cases} (IFWT(A_0)-IFWT(A_1),IFWT(A_1))&(n>0)\\ A(n=0) \end{cases} \]

过程类似,这里就不多赘述。。

\(Part6--IFWT(xor)\)

\(xor\)\(IFWT\)出人意料地一样简单。

由定义得:

\[ \begin{cases} FWT(A)_0=FWT(A_0)+FWT(A_1)\\ FWT(A)_1=FWT(A_0)-FWT(A_1) \end{cases} \]

解方程就简单了。

最后有:

\[ IFWT(A)=\begin{cases} (\frac{IFWT(A_0)+IFWT(A_1)}2,\frac{IFWT(A_0)-IFWT(A_1)}2)&(n>0)\\ A&(n=0) \end{cases} \]

终于完了


那么接下来就是看图写话看定义写代码过程了:

这里为了节省代码量把\(6\)个函数写一起了(因为框架大致类似)。

代码:

#include 
#include
typedef long long ll;const int Mod=998244353,Inv2=(Mod+1)>>1;//Inv2 2在mod998244353下的逆元int n,a[1<<17],b[1<<17],as[1<<17],bs[1<<17];void FWT(int *A,int op,int t)//op [1/-1][FWT/IFWT]//t [1,2,3][or/and/xor]{ for(int i=2;i<=n;i<<=1)//i 区间长度 for(int j=0,m=i>>1;j

代码应该很好懂,就不解释了。

我只能说:\(FWT\)真好背真好写。

参考资料:(\(Dalao\ TQL\)

转载于:https://www.cnblogs.com/LanrTabe/p/11305626.html

你可能感兴趣的文章
[Swift]LeetCode922.按奇偶排序数组 II | Sort Array By Parity II
查看>>
Html5 离线页面缓存
查看>>
《绿色·精简·性感·迷你版》易语言,小到不可想象
查看>>
Android打包key密码丢失找回
查看>>
VC6.0调试技巧(一)(转)
查看>>
类库与框架,强类型与弱类型的闲聊
查看>>
webView添加头视图
查看>>
php match_model的简单使用
查看>>
在NT中直接访问物理内存
查看>>
Intel HEX 文件格式
查看>>
SIP服务器性能测试工具SIPp使用指导(转)
查看>>
php_扑克类
查看>>
回调没用,加上iframe提交表单
查看>>
(安卓)一般安卓开始界面 Loding 跳转 实例 ---亲测!
查看>>
Mysql 索引优化 - 1
查看>>
LeetCode(3) || Median of Two Sorted Arrays
查看>>
大话文本检测经典模型:EAST
查看>>
待整理
查看>>
一次动态sql查询订单数据的设计
查看>>
C# 类(10) 抽象类.
查看>>