快速沃尔什变换(FWT)笔记
开头Orz hy,Orz yrx
部分转载自hy的博客
快速沃尔什变换,可以快速计算两个多项式的位运算卷积(即and,or和xor)
问题模型如下:
给出两个多项式$A(x)$,$B(x)$,求$C(x)$满足$C[i]=\sum\limits_{j⊗k=i}A[j]*B[k]$.
约定记号
$⊗$表示某种位运算(and,or和xor中的一种),若$a$,$b$是两个整数,则$a⊗b$表示对这两个数按位进行位运算;若$A$,$B$是两个多项式,则$A⊗B$表示对这两个多项式做如上卷积;两个多项式的点积用$·$表示。
FWT
感觉这个算法就是瞎凑出来的(大佬轻喷)
考虑对$A$和$B$做某种变换(类似FFT),使得变换之后对应位相乘之后逆运算就可以得到卷积$C(x)$。
那么这种变换$F(A)$(其中$A$是一个多项式)需要满足:
$F(A)·F(B)=F(A⊗B)$
$F(k\ast A)=k\ast F(A)$
$F(A+B)=F(A)+F(B)$
那就瞎凑呗,考虑用类似FFT的分治思想来解决,把多项式$A$的下标按照二进制最高位分类,最高位为0的记为$A_0$,为1的记为$A_1$,则$A=(A_0,A_1)$。
继续凑,设$F(A)=(k_{1}A_{0}+k_{2}A_{1},k_{3}A_{0}+k_{4}A_{1})$,那么要做的就是求出这四个常数。
不难发现$(k_{1},k_{2})$与$(k_{3},k_{4})$并没有本质上的区别,即求出了前半部分的多个解取其中两个代入即可。
将结果写作$(C_{0},C_{1})$,看回之前变换的定义,这里分类讨论:
对于$and$:
因为
$0⊗0=0$,$1⊗0=0$,$0⊗1=0$,$1⊗1=1$
所以
$(A_{0},A_{1})⊗(B_{0},B_{1})=(A_{0}⊗B_{0}+A_{0}⊗B_{1}+A_{1}⊗B_{0},A_{1}⊗B_{1})$
用两种方法表示$C$,可得
$(k_{1}A_{0}+k_{2}A_{1})·(k_{1}B_{0}+k_{2}B_{1})$
$=k_{1}(A_{0}⊗B_{0}+A_{0}⊗B_{1}+A_{1}⊗B_{0})+k_{2}(A_{1}⊗B_{1})$
拆括号得:
$k_{1}^{2}(A_{0}⊗B_{0})+k_{1}k_{2}(A_{0}⊗B_{1})+k_{1}k_{2}(A_{1}⊗B_{0})+k_{2}^{2}(A_{1}⊗B_{1})$
$=k_{1}(A_{0}⊗B_{0})+k_{1}(A_{0}⊗B_{1})+k_{1}(A_{1}⊗B_{0})+k_{2}(A_{1}⊗B_{1})$
则有:
$\begin{cases}
k_{1}=k_{1}^{2} \\
k_{1}=k_{1}k_{2} \\
k_{2}=k_{2}^{2}
\end{cases}$
解得$\begin{cases} k_{1}=0 \\k_{2}=0\end{cases}$或$\begin{cases} k_{1}=1 \\k_{2}=0\end{cases}$或$\begin{cases} k_{1}=1 \\k_{2}=1\end{cases}$
考虑到要可以逆变换,所以解不能选两个相同的或者两个零(类似于求逆矩阵),因此这里只能选$(0,1)$和$(1,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}$
对于$or$:$(A_{0},A_{1})⊗(B_{0},B_{1})=(A_{0}⊗B_{0},A_{0}⊗B_{1}+A_{1}⊗B_{0}+A_{1}⊗B_{1})$
正变换:$\begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}$
逆变换:$\begin{bmatrix} 0 & 1 \\ 1 & -1 \end{bmatrix}$
对于$xor$:$(A_{0},A_{1})⊗(B_{0},B_{1})=(A_{0}⊗B_{0}+A_{1}⊗B_{1},A_{0}⊗B_{1}+A_{1}⊗B_{0})$
正变换:$\begin{bmatrix} 1 & 1 \\ 1 & -1 \end{bmatrix}$
逆变换:$\begin{bmatrix} \frac{1}{2} & \frac{1}{2} \\ \frac{1}{2} & -\frac{1}{2} \end{bmatrix}$
代码(洛谷P4717):
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define OR 0
#define AND 1
#define XOR 2
using namespace std;
typedef long long ll;
const int mod=;
int inv2,bit,bitnum,n,m,a[],b[],a1[],a2[],a3[],b1[],b2[],b3[];
int fastpow(int x,int y){
int ret=;
for(;y;y>>=,x=(ll)x*x%mod){
if(y&)ret=(ll)ret*x%mod;
}
return ret;
}
void fwt(int s[],int n,int ty,int op){
for(int i=;i<=n;i<<=){
for(int j=;j<n;j+=i){
for(int k=;k<i/;k++){
int x=s[j+k],y=s[j+k+(i>>)];//A0,A1
if(op==){
if(ty==OR){
s[j+k+(i>>)]=(x+y)%mod;
}else if(ty==AND){
s[j+k]=(x+y)%mod;
}else{
s[j+k+(i>>)]=(x+mod-y)%mod;
s[j+k]=(x+y)%mod;
}
}else{
if(ty==OR){
s[j+k+(i>>)]=((ll)y-x+mod)%mod;
}else if(ty==AND){
s[j+k]=(ll)((ll)x+mod-y)%mod;
}else{
s[j+k+(i>>)]=(ll)((ll)x+mod-y)*inv2%mod;
s[j+k]=(ll)(x+y)*inv2%mod;
}
}
}
}
}
}
int main(){
scanf("%d",&bitnum);
bit=(<<bitnum);
inv2=fastpow(,mod-);
for(int i=;i<bit;i++)scanf("%d",&a[i]),a1[i]=a[i],a2[i]=a[i],a3[i]=a[i];
for(int i=;i<bit;i++)scanf("%d",&b[i]),b1[i]=b[i],b2[i]=b[i],b3[i]=b[i];
fwt(a1,bit,,);
fwt(a2,bit,,);
fwt(a3,bit,,);
fwt(b1,bit,,);
fwt(b2,bit,,);
fwt(b3,bit,,);
for(int i=;i<bit;i++){
a1[i]=(ll)a1[i]*b1[i]%mod;
a2[i]=(ll)a2[i]*b2[i]%mod;
a3[i]=(ll)a3[i]*b3[i]%mod;
}
fwt(a1,bit,,-);
fwt(a2,bit,,-);
fwt(a3,bit,,-);
for(int i=;i<bit;i++)printf("%d ",a1[i]);
printf("\n");
for(int i=;i<bit;i++)printf("%d ",a2[i]);
printf("\n");
for(int i=;i<bit;i++)printf("%d ",a3[i]);
return ;
}
快速沃尔什变换(FWT)笔记的更多相关文章
- FWT快速沃尔什变换学习笔记
FWT快速沃尔什变换学习笔记 1.FWT用来干啥啊 回忆一下多项式的卷积\(C_k=\sum_{i+j=k}A_i*B_j\) 我们可以用\(FFT\)来做. 甚至在一些特殊情况下,我们\(C_k=\ ...
- 一个数学不好的菜鸡的快速沃尔什变换(FWT)学习笔记
一个数学不好的菜鸡的快速沃尔什变换(FWT)学习笔记 曾经某个下午我以为我会了FWT,结果现在一丁点也想不起来了--看来"学"完新东西不经常做题不写博客,就白学了 = = 我没啥智 ...
- 快速沃尔什变换FWT
快速沃尔什变换\(FWT\) 是一种可以快速完成集合卷积的算法. 什么是集合卷积啊? 集合卷积就是在集合运算下的卷积.比如一般而言我们算的卷积都是\(C_i=\sum_{j+k=i}A_j*B_k\) ...
- 集合并卷积的三种求法(分治乘法,快速莫比乌斯变换(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,然后才开始想别的. 这次学了 FWT 以后,以后判断应该就很快了吧? 参考资料 FWT 详解 知识点 by neither_nor 集训队论文 2015 集合幂 ...
- 关于快速沃尔什变换(FWT)的一点学习和思考
最近在学FWT,抽点时间出来把这个算法总结一下. 快速沃尔什变换(Fast Walsh-Hadamard Transform),简称FWT.是快速完成集合卷积运算的一种算法. 主要功能是求:,其中为集 ...
- Codeforces 662C(快速沃尔什变换 FWT)
感觉快速沃尔什变换和快速傅里叶变换有很大的区别啊orz 不是很明白为什么位运算也可以叫做卷积(或许不应该叫卷积吧) 我是看 http://blog.csdn.net/liangzhaoyang1/ar ...
- 快速沃尔什变换(FWT)学习笔记 + 洛谷P4717 [模板]
FWT求解的是一类问题:\( a[i] = \sum\limits_{j\bigoplus k=i}^{} b[j]*c[k] \) 其中,\( \bigoplus \) 可以是 or,and,xor ...
- 快速沃尔什变换 (FWT)学习笔记
证明均来自xht37 的洛谷博客 作用 在 \(OI\) 中,\(FWT\) 是用于解决对下标进行位运算卷积问题的方法. \(c_{i}=\sum_{i=j \oplus k} a_{j} b_{k} ...
随机推荐
- 路飞学城Python-Day22
- Git:Git入门及基本命令
Git的结构: Git和代码托管中心 局域网环境下: 1)GitLab服务器 外网环境下: 2)github 3)码云 代码托管中心的任务:维护远程库 本地库和远程库的交互 团队内部协作 跨团队协作 ...
- Tomcat样例安全漏洞
[漏洞描述] Tomcat在使用的时候一般都直接官网下载源代码包直接使用. 默认情况下,Tomcat源码包里面包含了 examples 这个目录,这个目录主要实现一些样例页面的访问. 比如: ...
- UVALive 3231 Fair Share
Fair Share Time Limit: 3000ms Memory Limit: 131072KB This problem will be judged on UVALive. Origina ...
- 【BZOJ3270】博物馆 概率DP 高斯消元
链接: #include <stdio.h> int main() { puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢"); puts("网 ...
- poj 2488 A Knight's Journey(dfs+字典序路径输出)
转载请注明出处:http://blog.csdn.net/u012860063?viewmode=contents 题目链接:http://poj.org/problem? id=2488 ----- ...
- php利用href进行页面传值的正确姿势
首先在a.php中 <?php $a = "world"; echo "<a href='b.php?m=$a'>删除</a>"; ...
- IMP-00010: 不是有效的导出文件,标题验证失败
IMP-00010: 不是有效的导出文件,标题验证失败 IMP-00000: 未成功终止导入 在google上查找了一下,大概有两种情况: 1.imp/exp的版本不对,也就是说低版本的导出,可以 ...
- 关于Tool接口--------hadoop接口:extends Configured implements Tool 和 ToolRunner.run
我们在写Hadoop--map/reduce程序时,遇到使用按文件url来分析文件----------多表连接的DistributedCache方式,看不懂使用extends Configured i ...
- Linux换行符相关
Linux和windows中的换行符差异问题LINUX的换行符在Windows记事本打开不换行或出现黑点是由于Linux和windows中的换行符差异问题造成的. Unix系统里,每行结尾只有“< ...