快速沃尔什变换(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} ...
随机推荐
- SQL基本语句:2.基本表
SQL基本表的增删改
- 用私有构造器或枚举类型强化Singleton
Singleton指只有一个实例的类,只能被创建一次. 在Java1.5之前实现Singleton有两种方式,都是将构造器设为private并导出公有的静态成员实例. 第一种方式将公有的静态成员实例设 ...
- 一个helloword hibernate配置以及查询
搭建一个Hibernate环境,开发步骤: 1. 下载源码 版本:hibernate-distribution-3.6.0.Final 2. 引入jar文件 hibernate3.jar核心 + ...
- Java之Object类
0 引言 Object类是类层次结构的根,Java中所有的类从根本上都继承自这个类.Object类是Java中唯一没有父类的类. 其他所有的类,包括标准容器类,比如数组,都继承了Object类中的方法 ...
- 七、利用frp 穿透到内网的http/https网站,实现对外开放
有域名的话使用域名,没有域名的话使用IP注意80端口是否被已经安装使用的nginx占用,若被占用,可以换成其他端口,比如8080,,或者利用nginx的反向代理实现frp服务端与nginx共用80端口 ...
- 解决utf8' codec can't decode byte 0xe5 in position 0: unexpected end of data
使用unicode对象的话,除了这样使用u标记,还可以使用unicode类以及字符串的encode和decode方法. unicode类的构造函数接受一个字符串参数和一个编码参数,将字符串封装为一个u ...
- SQL SERVER-in,between,like
and 1 LIKE 操作符用于在 WHERE 子句中搜索列中的指定模式 ( 可以使用正则表达式) select * from [User] where UserName like '%r' -- 以 ...
- 10.2.0.4 to 10.2.0.5 Installation of Patch Set Release (Windows)
环境:10.2.0.4集群数据库zlm10g(双节点,zlm10g1,zlm10g2) 系统:Windows 2003 Server 64Bit 内存:2G RAM 存储:ASM 目标:把集群数据库从 ...
- HDU 4311 Contest 2
求的是曼哈顿距离.可以把X,Y的距离分开来求.其中,求X.Y的距离可以通过排序后递推的方式求出值的. #include <iostream> #include <algorithm& ...
- 在MAC下怎样用SSH连接远程LINUXserver
首页,打开MAC的命令终端,检查是不是用root用的登录的,假设不是的话请输入命令:sudo -i切换到root. 然后,输入:ssh ip地址,假设主机存在的话会提示你输入password,输入正确 ...