快速沃尔什变换(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} ...
随机推荐
- intell-
intellect: n.[U, C] the ability to think in a logical way and understand things, especially at an ad ...
- UNP学习笔记3——基本UDP套接字编程
1 概述 TCP和UDP网络编程存在一些本质的差异,主要是由于传输层的差别:UDP是无连接的不可靠的数据报协议,而TCP是面向连接的字节流协议. 下图是典型的UDP客户端和服务器之间的通信流程.客户不 ...
- 记一次html页面传值给另一个html并解码
前言 由于最近写项目用到layui中的table.render,好像是直接由当前html直接与后台controller取数据,由一方(后台)遍历列表给html,而如果当前html需要传值给这个后台co ...
- js单体内置对象
js单体内置对象:js的内置对象,是ECMAScritp提供的.不依赖于宿主环境的对象,我的理解就是在我们开发之前js里面就已经存在的对象.单体内置对象就是是不需要通过new来实例化的,例如我们的st ...
- Android 开发者必知的开发资源
英文原文:Bongzimo 翻译: ImportNew-黄小非 译文链接:http://www.importnew.com/3988.html Android 开发者必知的开发资源 随着Androi ...
- [CodeForces]529B Group Photo 2
AK爷GhostCai的电脑又蓝屏了Orz 贪心题,确定一个maxh,限定h不大于一个值.枚举maxh. check的时候的细节很多: 1.h>maxh但w<maxh交换的时候需要占用交换 ...
- 题解 P3978 【[TJOI2015]概率论】
这道题...好像是第一道我自己切出来的黑题... 先说一句,牛顿二项式蒟蒻并不会,可以说是直接套结论. 求诸位老爷轻喷. 这道题用卡特兰数搞. 卡特兰数这玩意从普及组初赛一路考到省选,十分有用. 如果 ...
- MySql的replace into 语句
MySQL REPLACE语句介绍 MySQL的REPLACE语句是一个MySQL扩展于SQL标准的语句. 官方定义:REPLACE works exactly like INSERT, except ...
- windows 64位上oracle 11g安装
每次下载安装都记不住,所以我总结一下,站在前人的肩膀上 原文地址:http://jingyan.baidu.com/article/48b558e33af4a57f39c09a42.html Orac ...
- Docker 管理工具的选择:Kubernetes 还是 Swarm?
[编者的话]选择Kubernetes 或者 Swarm 就像在将 Linux 桌面发行版的范围缩小到两个后选出一个最喜欢的.哪个更满足你的需要如何才是决定因素. [3 天烧脑式基于Docker的CI/ ...