开头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)笔记的更多相关文章

  1. FWT快速沃尔什变换学习笔记

    FWT快速沃尔什变换学习笔记 1.FWT用来干啥啊 回忆一下多项式的卷积\(C_k=\sum_{i+j=k}A_i*B_j\) 我们可以用\(FFT\)来做. 甚至在一些特殊情况下,我们\(C_k=\ ...

  2. 一个数学不好的菜鸡的快速沃尔什变换(FWT)学习笔记

    一个数学不好的菜鸡的快速沃尔什变换(FWT)学习笔记 曾经某个下午我以为我会了FWT,结果现在一丁点也想不起来了--看来"学"完新东西不经常做题不写博客,就白学了 = = 我没啥智 ...

  3. 快速沃尔什变换FWT

    快速沃尔什变换\(FWT\) 是一种可以快速完成集合卷积的算法. 什么是集合卷积啊? 集合卷积就是在集合运算下的卷积.比如一般而言我们算的卷积都是\(C_i=\sum_{j+k=i}A_j*B_k\) ...

  4. 集合并卷积的三种求法(分治乘法,快速莫比乌斯变换(FMT),快速沃尔什变换(FWT))

    也许更好的阅读体验 本文主要内容是对武汉市第二中学吕凯风同学的论文<集合幂级数的性质与应用及其快速算法>的理解 定义 集合幂级数 为了更方便的研究集合的卷积,引入集合幂级数的概念 集合幂级 ...

  5. 【学习笔鸡】快速沃尔什变换FWT

    [学习笔鸡]快速沃尔什变换FWT OR的FWT 快速解决: \[ C[i]=\sum_{j|k=i} A[j]B[k] \] FWT使得我们 \[ FWT(C)=FWT(A)*FWT(B) \] 其中 ...

  6. 快速沃尔什变换 FWT 学习笔记【多项式】

    〇.前言 之前看到异或就担心是 FWT,然后才开始想别的. 这次学了 FWT 以后,以后判断应该就很快了吧? 参考资料 FWT 详解 知识点 by neither_nor 集训队论文 2015 集合幂 ...

  7. 关于快速沃尔什变换(FWT)的一点学习和思考

    最近在学FWT,抽点时间出来把这个算法总结一下. 快速沃尔什变换(Fast Walsh-Hadamard Transform),简称FWT.是快速完成集合卷积运算的一种算法. 主要功能是求:,其中为集 ...

  8. Codeforces 662C(快速沃尔什变换 FWT)

    感觉快速沃尔什变换和快速傅里叶变换有很大的区别啊orz 不是很明白为什么位运算也可以叫做卷积(或许不应该叫卷积吧) 我是看 http://blog.csdn.net/liangzhaoyang1/ar ...

  9. 快速沃尔什变换(FWT)学习笔记 + 洛谷P4717 [模板]

    FWT求解的是一类问题:\( a[i] = \sum\limits_{j\bigoplus k=i}^{} b[j]*c[k] \) 其中,\( \bigoplus \) 可以是 or,and,xor ...

  10. 快速沃尔什变换 (FWT)学习笔记

    证明均来自xht37 的洛谷博客 作用 在 \(OI\) 中,\(FWT\) 是用于解决对下标进行位运算卷积问题的方法. \(c_{i}=\sum_{i=j \oplus k} a_{j} b_{k} ...

随机推荐

  1. 系统中 CPU 时间片是多久

    Windows 系统中线程轮转时间也就是时间片大约是20ms,如果某个线程所需要的时间小于20ms,那么不到20ms就会切换到其他线程:如果一个线程所需的时间超过20ms,系统也最多只给20ms,除非 ...

  2. debian系统包管理工具aptitude

    注意:aptitude与 apt-get 一样,是 Debian 及其衍生系统中功能极其强大的包管理工具.与 apt-get 不同的是,aptitude在处理依赖问题上更佳一些.举例来说,aptitu ...

  3. Postgresql数据库的一些字符串操作函数

    今天做项目遇到客户反映了一个麻烦的事情,有一些数据存在,但就是在程序中搜索不出来,后来分析,发现问题为数据前面有几个空白字符,后来用SQL查询了一下,发现八九个数据表中,数千万条数据中有将近三百万条数 ...

  4. [luogu] P4551 最长异或路径(贪心)

    P4551 最长异或路径 题目描述 给定一棵\(n\)个点的带权树,结点下标从\(1\)开始到\(N\).寻找树中找两个结点,求最长的异或路径. 异或路径指的是指两个结点之间唯一路径上的所有边权的异或 ...

  5. 洛谷 1052 dp 状态压缩

    洛谷1052 dp 状态压缩 传送门 (https://www.luogu.org/problem/show?pid=1052#sub) 做完这道题之后,感觉涨了好多见识,以前做的好多状压题目都是将一 ...

  6. 关于thinkpadU盘系统盘启动不了解决方法

    http://www.laomaotao.org/softhelp/bios/382.html(原文章地址,比较全面) thinkpad笔记本uefi无法启动详细解决教程 最近有个别用户反映说thin ...

  7. springboot启动嵌入式tomcat报错找不到jar包,关键字:FileNotFoundException,derbyLocale_cs.jar,StandardJarScanner.scan

    异常: java.io.FileNotFoundException: /Users/lanhuajian/.m2/repository/org/apache/derby/derby/10.13.1.1 ...

  8. 走进windows编程的世界-----入门篇

    1   Windows编程基础 1.1Win32应用程序基本类型 1)  控制台程序 不须要完好的windows窗体,能够使用DOS窗体方式显示 2)  Win32窗体程序 包括窗体的程序,能够通过窗 ...

  9. 关于Android的.so文件所须要知道的

    早期的Android系统差点儿仅仅支持ARMv5的CPU架构,你知道如今它支持多少种吗?7种. Android系统眼下支持以下七种不同的CPU架构:ARMv5.ARMv7 (从2010年起),x86 ...

  10. 1067. Sort with Swap(0,*) (25)【贪心】——PAT (Advanced Level) Practise

    题目信息 1067. Sort with Swap(0,*) (25) 时间限制150 ms 内存限制65536 kB 代码长度限制16000 B Given any permutation of t ...