关于快速沃尔什变换(FWT)的一些个人理解
定义
FWT是一种快速完成集合卷积运算的算法。
它可以用于求解类似 $C[i]=\sum\limits_{j⊗k=i}A[j]*B[k]$ 的问题。
其中⊗代表位运算中的|,&,^的其中一种。
求解(正变换)
设F(A)是对于A的一种变换。
并且F(A)要求满足:
$F(A)*F(B)=F(A⊗B)$ ①
$k*F(A)=F(k*A)$ ②
$F(A+B)=F(A)+F(B)$ ③ (A,B长度相同)
鉴于FWT和FFT长得特别像(而且求解的问题也比较类似),我们可以借鉴一下FFT的思路,采用分治的想法。
首先先把多项式的长度用0补到2n,即多项式A为a0+a1x+a2x2+.....+a2n-1x2^n-1。
我们可以将多项式A拆成A0和A1。A0为多项式下标二进制最高位为0的部分,A1即为多项式下标二进制最高位为1的部分。
则A=(A0,A1)。 (ps:此处的括号意为将A0,A1拼起来。)
我们猜测F(A)=(k1*F(A0)+k2*F(A1),k3*F(A0)+k4*F(A1)),其中当A的长度为1时,F(A)=A
对于②式证明如下:
假设A的长度为2n,
由原式得:(k1*F(A0)+k2*F(A1),k3*F(A0)+k4*F(A1))*k=
(k1*F(k*A0)+k2*F(k*A1),k3*F(k*A0)+k4*F(k*A1))
则若要证明k*F(A)=F(k*A),我们需要证明的是F(k*A')=k*F(A'),其中A'的长度为2n-1。按照此方法递归直到A的长度为1,因为k*A=k*A,所以k*F(A)=F(k*A)。证毕。
对于③式证明如下:(其实和②式的证明一样的)
假设A,B的长度为2n。
由原式得:(k1*F(A0+B0)+k2*F(A1+B1),k3*F(A0+B0)+k4*F(A1+B1))=
(k1*F(A0)+k2*F(A1),k3*F(A0)+k4*F(A1))+(k1*F(B0)+k2*F(B1),k3*F(B0)+k4*F(B1))
则若要证明F(A+B)=F(A)+F(B),需要条件F(A'+B')=F(A')+F(B'),其中A'的长度为2n-1。照此方法递归,同理可证明。
如今我们证明了②③的正确性,以下计算是为了确保①正确。
(以下计算以异或为例)
由 F(C)=F(A)*F(B)
C=A⊗B→ (A0,A1)⊗(B0,B1)=(A0⊗B0+A1⊗B1,A1⊗B0+A0⊗B1)
可以得出 (以下我们以k1,k2为例)
F(A)的前半部分 F(B)的前半部分 F(C)的前半部分
↓ ↓ ↓
(k1*F(A0)+k2*F(A1))*(k1*F(B0)+k2*F(B1))
=k1*F(A0⊗B0+A1⊗B1)+k2*F(A1⊗B0+A0⊗B1)
所以 k12F(A0⊗B0)+k1k2*F(A0⊗B1)+k1k2*F(A1⊗B0)+k22F(A1⊗B1)
=k1*F(A0⊗B0)+k2*F(A0⊗B1)+k2*F(A1⊗B0)+k1*F(A1⊗B1)
可得k12=k1,k1k2=k2,k22=k1。
解得k1,k2为(0,0)或(1,1)或(1,-1)
由于我们的操作必须可逆,所以排除掉(0,0),并且(k1,k2)(k3,k4)不相等。所以我们可以令k1=k2=k3=1,k4=-1。
则逆变换的时候,k1=k2=k3=1/2,k4=-1/2(这个解一下方程就可以算出来了)。
如果是|或者&运算,将红色部分修改为:
| :(A0,A1)⊗(B0,B1)=(A0⊗B0,A1⊗B0+A0⊗B1+A1⊗B1)
& : (A0,A1)⊗(B0,B1)=(A0⊗B0+A1⊗B0+A0⊗B1,A1⊗B1)
以下代码都以异或为例
void fwt(int *a,int len)//xor
{
for (int i=;i<len;i<<=)
for (int j=;j<len;j+=i*)
for (int k=;k<i;k++)
{
int u=a[j+k],v=a[j+k+i];
a[j+k]=u+v;a[j+k+i]=u-v+mod;
if (a[j+k]>mod) a[j+k]-=mod;
if (a[j+k+i]>mod) a[j+k+i]-=mod;
// or:a[j+k+i]=u+v;
// and:a[j+k]=u+v;
}
}
FWT逆变换代码(以异或为例)
void ufwt(int *a,int len)
{
for (int i=;i<len;i<<=)
for (int j=;j<len;j+=i*)
for (int k=;k<i;k++)
{
int x=a[j+k],y=a[j+k+i];
a[k+j]=(x+y)*inv2%mod;
a[j+k+i]=(x-y+mod)*inv2%mod;
}
}
其中的inv2为2的逆元。如果题目没有要求将答案除以某数,也可以写作:a[k+j]=(x+y)/2,a[k+j+i]=(x-y)/2
一个神神秘秘的问题
学习FWT的时候我比较好奇一个问题。在正变换的时候我们先处理F(A0),F(A1)后处理F(A),那为什么我们在求逆变换的时候不需要先求F(A)的逆变换再处理F(A0),F(A1)的。。。
请大佬不吝赐教。
本篇博客参考hy大佬的博客http://www.cnblogs.com/yoyoball/p/9260176.html。对于其一些我不太理解的地方加了证明和改动。如果有错误之处还请多多包涵。
关于快速沃尔什变换(FWT)的一些个人理解的更多相关文章
- 一个数学不好的菜鸡的快速沃尔什变换(FWT)学习笔记
一个数学不好的菜鸡的快速沃尔什变换(FWT)学习笔记 曾经某个下午我以为我会了FWT,结果现在一丁点也想不起来了--看来"学"完新东西不经常做题不写博客,就白学了 = = 我没啥智 ...
- 集合并卷积的三种求法(分治乘法,快速莫比乌斯变换(FMT),快速沃尔什变换(FWT))
也许更好的阅读体验 本文主要内容是对武汉市第二中学吕凯风同学的论文<集合幂级数的性质与应用及其快速算法>的理解 定义 集合幂级数 为了更方便的研究集合的卷积,引入集合幂级数的概念 集合幂级 ...
- 【学习笔鸡】快速沃尔什变换FWT
[学习笔鸡]快速沃尔什变换FWT OR的FWT 快速解决: \[ C[i]=\sum_{j|k=i} A[j]B[k] \] FWT使得我们 \[ FWT(C)=FWT(A)*FWT(B) \] 其中 ...
- 快速沃尔什变换FWT
快速沃尔什变换\(FWT\) 是一种可以快速完成集合卷积的算法. 什么是集合卷积啊? 集合卷积就是在集合运算下的卷积.比如一般而言我们算的卷积都是\(C_i=\sum_{j+k=i}A_j*B_k\) ...
- 关于快速沃尔什变换(FWT)的一点学习和思考
最近在学FWT,抽点时间出来把这个算法总结一下. 快速沃尔什变换(Fast Walsh-Hadamard Transform),简称FWT.是快速完成集合卷积运算的一种算法. 主要功能是求:,其中为集 ...
- 快速沃尔什变换 FWT 学习笔记【多项式】
〇.前言 之前看到异或就担心是 FWT,然后才开始想别的. 这次学了 FWT 以后,以后判断应该就很快了吧? 参考资料 FWT 详解 知识点 by neither_nor 集训队论文 2015 集合幂 ...
- Codeforces 662C(快速沃尔什变换 FWT)
感觉快速沃尔什变换和快速傅里叶变换有很大的区别啊orz 不是很明白为什么位运算也可以叫做卷积(或许不应该叫卷积吧) 我是看 http://blog.csdn.net/liangzhaoyang1/ar ...
- HDU 5977 Garden of Eden (树形dp+快速沃尔什变换FWT)
CGZ大佬提醒我,我要是再不更博客可就连一月一更的频率也没有了... emmm,正好做了一道有点意思的题,就拿出来充数吧=.= 题意 一棵树,有 $ n (n\leq50000) $ 个节点,每个点都 ...
- BZOJ4589 Hard Nim(快速沃尔什变换FWT)
这是我第一道独立做出来的FWT的题目,所以写篇随笔纪念一下. (这还要纪念,我太弱了) 题目链接: BZOJ 题目大意:两人玩nim游戏(多堆石子,每次可以从其中一堆取任意多个,不能操作就输).$T$ ...
- 快速沃尔什变换(FWT)学习笔记 + 洛谷P4717 [模板]
FWT求解的是一类问题:\( a[i] = \sum\limits_{j\bigoplus k=i}^{} b[j]*c[k] \) 其中,\( \bigoplus \) 可以是 or,and,xor ...
随机推荐
- 无法执行程序。所执行的命令为 "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe" /noconfig /fullpaths @"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\b411ea32\b48a9fb\aun5r0xd.c
解决方案 将应用程序池进程模型中的标识设为“LocalSystem”即可.
- Linux下的MBR分区
MBR分区 下面讲一讲如何给一块新添加入服务器的硬盘做MBR分区,那么为什么叫做MBR分区呢?后面会讲 做MBR分区,使用系统自带的fdisk工具.先看一看什么是fdisk,在命令行输入“fdisk” ...
- 2、Sublime Text 3 快捷键(实用,快速换行等)
选择类 Ctrl+D :选中光标所占的文本,继续操作则会选中下一个相同的文本. Alt+F3:选中文本按下快捷键,即可一次性选择全部的相同文本进行同时编辑.举个栗子:快速选中并更改所有相同的变量名.函 ...
- flask开启debug模式的两种方法、加载配置文件的两种方法、URL传参的四种方法
from flask import Flask app = Flask(__name__) # app.config.update(DEBUG=True)#开启debug模式 #加载配置文件方法一 # ...
- 2、RabbitMQ-simplest thing(简单队列)
1.项目准备: 使用maven的依赖 <dependencies> <dependency> <groupId>com.rabbitmq</groupId&g ...
- 【luogu P1850 换教室】 题解
题目链接:https://www.luogu.org/problemnew/show/P1850 难的不在状态上,难在转移方程. (话说方程写错居然还有84分= =) #include <cst ...
- ovs的卸载删除
参考博客1 参考博客2 需要更新.重装ovs时需要先卸载. 删除网桥.端口 ovs-vsctl del-br 交换机名 ovs-vsctl del-port 交换机名 端口名(网卡名) 关闭服务 su ...
- Visual Studio 2017 安装过程问题解决
VS已经发布了两三天了,我也着手安装,但是折腾了两个晚上,怎么都到不了安装界面(选择模块的界面),各种尝试,各种重启,也并不顶什么卵用~ 后来经过各种查LOG,发现我电脑访问不了https://dow ...
- page_address()函数分析--如何通过page取得虚拟地址
由于X86平台上面,内存是划分为低端内存和高端内存的,所以在两个区域内的page查找对应的虚拟地址是不一样的. 一. x86上关于page_address()函数的定义 在include/linux/ ...
- 【HTML-进阶-如何实现父级块级元素宽度自适应子元素宽度】
背景 块级元素宽度默认值为100%,而不是auto;因此其宽度不会根据子元素内容动态适应. 如何实现父级元素宽度动态适应其子元素. 方法一 display:inline; 给块级元素设置inline- ...