【learning】快速沃尔什变换FWT
问题描述
已知\(A(x)\)和\(B(x)\),\(C[i]=\sum\limits_{j\otimes k=i}A[j]*B[k]\),求\(C\)
其中\(\otimes\)是三种位运算的其中一种
具体求解
说在前面:接下来的一些符号的话我们统一用\(\otimes\)代表某种位运算(选定的),如果这个符号出现在两个多项式之间(如:\(A\otimes B\)),那么是表示按照最上面那条式子卷积,如果出现在两个数之间(如\(j\otimes k\)),那么是表示这两个数进行这种位运算;然后我们用$ \cdot$这个符号表示点积(也就是对应数位相乘)
这里我们用与运算(\(\otimes=\&\))举例说明好了,另外两个差不多的
首先来个不太靠谱的联想,这个东西的名字长得跟FFT那么像那是不是可以借用FFT的形式啊(Portal -->FFT)
然后我们考虑构造一种变换\(F(A)\)(额其实就是FWT),其中\(A\)是一个多项式,这个变换满足:
\[ \begin{aligned} &F(A)\cdot F(B)=F(A\otimes B)\\ &F(k* A)=k*F(A)\\ &F(A+B)=F(A)+F(B)\\ \end{aligned} \]
这样我们就可以像FFT一样,先用某种方法求出\(F(A)\)和\(F(B)\)然后对应位相乘,再把得到的结果逆变换一下就可以得到\(C(x)\)了
那么现在的问题是我们怎么构造\(F\)
参考FFT的求解我们还是尝试用分治的思想来解决这个问题
与FFT按照下标的奇偶性分类不同,因为位运算是跟二进制有关的,所以我们可以考虑按照下标的二进制最高位为\(0\)还是为\(1\)分成两类(因为算的时候长度是补成\(2^k\)这样的,所以其实也就是严格的前半部分和后半部分)
对于一个多项式\(A\),下标二进制最高位为\(0\)的那部分记为\(A_0\),为\(1\)的那部分记为\(A_1\),\(A=(A_0,A_1)\)
我们可以猜测一下这个\(F(A)=(k_1A_0+k_2A_1,k_3A_0+k_4A_1)\)
其中\(k_1,k_2,k_3,k_4\)都是常数
然后现在我们要做的就是求出这四个常数
我们将\(A\otimes B\)写成\((A_0,A_1)\otimes (B_0,B_1)\),然后看一下这个式子等于什么:
同样的我们还是将结果写成\((C_0,C_1)\)的形式,那么根据与运算的特点我们可以的到:
\[ \begin{aligned} (A_0,A_1)\otimes (B_0,B_1)=(A_0\otimes B_0+A_0\otimes B_1+A_1\otimes B_0,A_1\otimes B_1)\\ \end{aligned} \]
(具体一点的话就是\(0\&0=0,0\&1=0,1\&0=0\)所以都是\(C_0\)的组成部分,只有\(1\&1=1\)是\(C_1\)的组成部分)
然后我们根据最上面的\(F\)这个变换满足的性质和我们猜测的\(F(A)=(k_1A_0+k_2A_1,k_3A_0+k_4A_1)\)来处理一下这个式子
(因为\(k_1,k_2\)和\(k_3,k_4\)满足的条件其实是一样的所以在下面化的时候我们可以只考虑前半部分的求解(也就是就解\(k_1,k_2\),所有的变换什么的只写前半部分),然后求得多组解最后取其中两个可行解分别作为\(k_1,k_2,k_3,k_4\)即可)
(因为太长了。。所以一个等式我就换行来写了qwq)
\[ \begin{aligned} &(k_1A_0+k_2A_1)\cdot (k_1B_0+k_2B_1)\\ =&k_1(A_0\otimes B_0+A_0\otimes B_1+A_1\otimes B_0)+ k_2(A_1\otimes B_1)\\ \\ &\Updownarrow\\ \\ &k_1^2(A_0\otimes B_0)+k_1k_2(A_0\otimes B_1)+k_1k_2(A_1\otimes B_0)+k_2^2(A_1\otimes B_1)\\ =&k_1(A_0\otimes B_0)+k_1(A_0\otimes B_1)+k_1(A_1\otimes B_0)+k_2(A_1\otimes B_1) \end{aligned} \]
然后我们就可以直接得到一个比较好看的方程组了:
\[ \begin{cases} k_1^2=k_1\\ k_1k_2=k_1\\ k_2^2=k_2\\ \end{cases} \]
然后我们解出来有三组解:\((0,0),(1,1),(0,1)\)
接下来要做的就是从这三组解里面挑两组出来作为\((k_1,k_2)\)和\((k_3,k_4)\)
但这个并不是随便挑的,考虑到我们的这个变换必须要有一个逆变换,所以我们挑出来的两组不能是有一组是\((0,0)\)或者有两组相等(不然就不可逆了嘛),实际上,我们可以将这四个系数写成一个矩阵,然后逆变换的系数的话就是对这个矩阵求个逆就好了
所以,这里我们只能选\((1,1)\)和\((0,1)\),我们令\((k_1,k_2)=(1,1)\),\((k_3,k_4)=(0,1)\)
\[ \begin{bmatrix} k_1&k_2\\ k_3&k_4\\ \end{bmatrix}= \begin{bmatrix} 1&1\\ 0&1\\ \end{bmatrix} \]
然后我们把这个东西求一下逆,得到逆矩阵:
\[ \begin{bmatrix} 1&-1\\ 0&1\\ \end{bmatrix} \]
(具体求解的话。。当然可以直接用线代的那套但是qwq这里那么小那直接设数代一下就好了,设四个数然后矩乘一下等于单位矩阵)
然后我们按照这个系数去算FWT(也就是变换\(F\))和逆FWT就好啦
然后如果是求异或或者是或运算的话,那直接改一下
\[ (A_0,A_1)\otimes (B_0,B_1)=(A_0\otimes B_0+A_0\otimes B_1+A_1\otimes B_0,A_1\otimes B_1) \]
这个式子的左边然后再用同样的方法算一下就好了
xor的话就是:\((A_0\otimes B_0+A_1\otimes B_1,A_0\otimes B_1+A_1\otimes B_0)\)
or的话就是:\((A_0\otimes B_0,A_0\otimes B_1+A_1\otimes B_0+A_1\otimes B_1)\)
代码什么的长得跟FFT其实差不多。。。哦不对。。会短很多ovo
大概是长这个样子:
#define OR 0
#define AND 1
#define XOR 2void fwt(int *a,int op,int type,int len){//op=1为FWT,否则为逆FWTint v,u;for (int step=2;step<=len;step<<=1)for (int st=0;st<len;st+=step)for (int i=0;i<step>>1;++i){u=a[st+i]; v=a[st+i+(step>>1)];//u=A0,v=A1if (op==1){if (type==XOR)a[st+i]=(u+v)%MOD,a[st+i+(step>>1)]=(u+MOD-v)%MOD;else if (type==AND)a[st+i]=(u+v)%MOD;elsea[st+i+(step>>1)]=(u+v)%MOD;}else{if (type==XOR)a[st+i]=1LL*(u+v)*inv2%MOD,a[st+i+(step>>1)]=1LL*(1LL*u+MOD-v)*inv2%MOD;else if (type==AND)a[st+i]=(1LL*u-v+MOD)%MOD;elsea[st+i+(step>>1)]=(1LL*v-u+MOD)%MOD;//v-u!!}}
}
转载于:https://www.cnblogs.com/yoyoball/p/9260176.html
【learning】快速沃尔什变换FWT相关推荐
- 解题报告(一)快速沃尔什变换FWT(ACM / OI)超高质量题解
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...
- 快速沃尔什变换(FWT)
1前言 在之前学完了FFT稍微码了一些题.也学习了一下NTT相关的知识之后,我觉得有必要学习一下FWT,这篇博客就是阐述我对FWT的理解的 2介绍 2.1解决的问题 对于FFT,它的过程本质上是cn= ...
- [学习笔记]快速沃尔什变换 (FWT)
FWT的简介 一般 FWT \text{FWT} FWT用来解决一下问题: C k = ∑ i ∣ j = k A i B j C_k=\sum_{i|j=k}A_iB_j Ck=∑i∣j=kAi ...
- 快速沃尔什变换(FWT)及K进制异或卷积快速子集变换(FST)讲解
前言: $FWT$是用来处理位运算(异或.与.或)卷积的一种变换.位运算卷积是什么?形如$f[i]=\sum\limits_{j\oplus k==i}^{ }g[j]*h[k]$的卷积形式(其中$\ ...
- 快速沃尔什变换(FWT) 学习笔记
最近在做多校联赛的题目,发现有一道题需要用到FWT,于是我就去学了一下.膜拜一下大神,本篇博客仅对这篇博客进行一些细节上的补充. FWT要解决的问题是 Ck=∑i⊕j=kai∗bi {C}_{k}=\ ...
- 《小学生都能看懂的快速沃尔什变换从入门到升天教程》(FWT / FMT / FMI)(最最严谨清晰的证明!零基础也能得学会!)
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 0x00 卷积 0x01 多项式 0x02 卷积的定义 0x03 卷积的基本性质 0x04 位运 ...
- 快速沃尔什变换(FWT)讲解 解决集合卷积的方法
由于某次CSDN更新,文章样式已经丢失,大量公式无法正常显示,本博客也不再维护. 请到快速沃尔什变换FWT查看,有更加完整的公式讲解. 能看到这篇博客的人,一定知道FWT是干什么的.(什么?你不知道? ...
- [多项式算法](Part 4)FWT 快速沃尔什变换 学习笔记
其他多项式算法传送门: [多项式算法](Part 1)FFT 快速傅里叶变换 学习笔记 [多项式算法](Part 2)NTT 快速数论变换 学习笔记 [多项式算法](Part 3)MTT 任意模数FF ...
- [模板] 快速沃尔什变换
快速沃尔什变换 快速沃尔什变换是求这样的式子: 对序列 \(A\), \(B\), 求序列 \(C\), 使得 \[ C_{i}=\sum_{j \oplus k} A_{j} B_{k} \] 其中 ...
最新文章
- 基于OHCI的USB主机 —— UFI数据结构1
- form表单中的常用控件
- Too Many Segments (hard version) CodeForces - 1249D2(贪心+容器vector+set)
- 2008年不错的图书
- 函数中结构体指针作为形参修改指针地址
- vivado global和out-of-context 选项
- 【模板】 线段树(部分功能)
- Bundle Adjustment原理及应用
- css的优先级及复合选择器权重计算
- 调试和测试 Swing 代码
- IBM System 服务器做RAID步骤
- iText PDF操作(查找关键字、插入图片)
- php 修改图像大小,如何改变图片大小
- dubbo 的SPI机制Adaptive适配
- matlab求解积分总结
- PHP中date时差问题解决方法
- 【STM32】NRF24L01模块的收发调试
- 百词斩2021高频题汇总 | 备战春招,刷这30题就够了!
- set name utd8_ml utd 8机器学习数据的最新生命
- 亚德诺半导体收购竞争对手美信;凯西与拜耳将在华共同推广宝丽亚和启尔畅 | 美通企业日报...
热门文章
- python yield 简单用法_python中 yield 的用法 (简单、清晰)
- docker mysql镜像连接不上_还在手动安装应用?试一下Docker
- 测试计划(GB8567——88)
- mybatis的SelectKey属性的作用
- hadoop日志文件
- GitLab CI持续集成配置方案
- SpringCloud 教程 | 第一篇: 服务的注册与发现(Eureka)
- Java 线程状态之 TIMED_WAITING
- Spring MVC 解读——@Autowired、@Controller、@Service从原理层面来分析
- OkHttp实现登录注册验证