## 问题描述

  已知\(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. 《C++设计新思维》勘误,附C++14新解法

    勘误: 原书(中文版)3.13节,65-69页中GenScatterHierarchy以及FieldHelper均存在问题,当TypeList中类型有重复时,无法通过编译(原因在于“二义性基类”). ...

  2. iOS 播放音频文件

    //        播放音乐 NSString *path = [[NSBundle mainBundle] pathForResource:@"1670" ofType:@&qu ...

  3. Tree Traversals Again(根据前序,中序,确定后序顺序)

    题目的大意是:进行一系列的操作push,pop.来确定后序遍历的顺序 An inorder binary tree traversal can be implemented in a non-recu ...

  4. 【转】AOE机制的DSL及其实际运用

    AOE这个词的意思,我相信玩过WOW的人都不陌生,包括玩过LoL的也不会陌生,说穿了就是一个区域内发生效果(Area of effect).这里我们要讨论的就是关于一个适合于几乎所有游戏的AOE机制, ...

  5. 论文笔记:Visualizing and Understanding Convolutional Networks

    2014 ECCV 纽约大学 Matthew D. Zeiler, Rob Fergus 简单介绍(What) 提出了一种可视化的技巧,能够看到CNN中间层的特征功能和分类操作. 通过对这些可视化信息 ...

  6. .NET 4.0 Tuple 元组

    Tuple是.NET 4.0的新特性,主要功能是动态返回数据结构,也可以用做临时数据结构. 原来做一些功能时需要一个方法返回几个值,有两种方法: 1. 非常难看.难用的OUT参数: 2. 新写一个实体 ...

  7. 2014-2015 ACM-ICPC, NEERC, Eastern Subregional Contest Problem H. Pair: normal and paranormal

    题目链接:http://codeforces.com/group/aUVPeyEnI2/contest/229669 时间限制:1s 空间限制:64MB 题目大意:给定一个长度为2n,由n个大写字母和 ...

  8. 在原有的基础之上,启用NAT模型

    # 给虚拟主机实例添加一个网关 route add default gw 192.168.23.1   # 在宿主机打开网卡间转发功能 echo 1 > /proc/sys/net/ipv4/i ...

  9. PAT 甲级 1099 Build A Binary Search Tree

    https://pintia.cn/problem-sets/994805342720868352/problems/994805367987355648 A Binary Search Tree ( ...

  10. oracle 行转列和列转行

    WITH L AS ( ), m AS ( SELECT A.LV AS LV_A, B.LV AS LV_B, TO_CHAR(B.LV) || 'x' || TO_CHAR(A.LV) || '= ...