## 问题描述

  已知\(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 2 void fwt(int *a,int op,int type,int len){//op=1为FWT,否则为逆FWT
int 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=A1
if (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;
else
a[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;
else
a[st+i+(step>>1)]=(1LL*v-u+MOD)%MOD;//v-u!!
}
}
}

【learning】快速沃尔什变换FWT的更多相关文章

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

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

  2. 快速沃尔什变换FWT

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

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

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

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

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

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

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

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

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

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

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

  8. HDU 5977 Garden of Eden (树形dp+快速沃尔什变换FWT)

    CGZ大佬提醒我,我要是再不更博客可就连一月一更的频率也没有了... emmm,正好做了一道有点意思的题,就拿出来充数吧=.= 题意 一棵树,有 $ n (n\leq50000) $ 个节点,每个点都 ...

  9. BZOJ4589 Hard Nim(快速沃尔什变换FWT)

    这是我第一道独立做出来的FWT的题目,所以写篇随笔纪念一下. (这还要纪念,我太弱了) 题目链接: BZOJ 题目大意:两人玩nim游戏(多堆石子,每次可以从其中一堆取任意多个,不能操作就输).$T$ ...

随机推荐

  1. 学习HTML 第五节.简单交互 加个按钮

    学习HTML 第五节.简单交互 也许你和我一样,对页面排版的兴趣小于网页交互,那么我们就先略过一些章节,直接先学一下简单交互. 前面点击图片打开链接的网址,已经是最简单的交互方式了,复杂的方式则需要用 ...

  2. Web性能测试篇:AB 压力测试

    1. 压力测试的概念\定义 1.这段话是给刚接触\学习性能测试知识的初学者,在实际工作中都会接触到性能测试.压力测试.负载测试等专业名词也容易混淆,下面带大家熟悉下这到底是怎么定义: 1.1.性能测试 ...

  3. GitHub 多人协作开发 三种方式:

    GitHub 多人协作开发 三种方式: 一.Fork 方式 网上介绍比较多的方式(比较大型的开源项目,比如cocos2d-x) 开发者 fork 自己生成一个独立的分支,跟主分支完全独立,pull代码 ...

  4. 排查GCC 4.4.X版本优化switch-enum的BUG

    起因 一次偶然碰到一个诡异的bug,现象是同一份C++代码使用GCC4.4.x版本在开启优化前和优化后的结果不一样,优化后的代码逻辑不正确. 示例代码如下: //main.cpp #include & ...

  5. POJ 1417 并查集 dp

    After having drifted about in a small boat for a couple of days, Akira Crusoe Maeda was finally cast ...

  6. spring mvc 详细配置

    转自: http://www.cnblogs.com/superjt/p/3309255.html 现在主流的Web MVC框架除了Struts这个主力 外,其次就是Spring MVC了,因此这也是 ...

  7. c艹第三次作业

    1.git地址,不要介意仓库名. https://github.com/b666666666666666b/elevator-schedualing 2.首先,我先说一下我是怎么实现三个电梯的. 首先 ...

  8. Java微笔记(6)

  9. Hexo博客搭建全解

    [原创,转载请附网址:http://dongshuyan.top] 欢迎来到莫与的博客,第一篇记录了一下怎么写一篇博客,以方便之后写博客~ #从配置说起下载安装Git与Node.js略过 1.安装he ...

  10. C#高级编程 (第六版) 学习 第六章:运算符和类型强制转换

    第六章 运算符和类型强制转换 1,运算符 类别 运算符 算术运算符 + - * / % 逻辑运算符 & | ^ ~ && || ! 字符串连接运算符 + 增量和减量运算符 ++ ...