$\text {FWT}$学习笔记
\(\text {FWT}\) 学习笔记
正常项的\(\text {FWT}\)
在\(\text {OI}\)中,我们经常会碰到这种问题:
- 给出一个长度为\(n\)的序列\(a_{1,2,...,n},b_{1,2,...,n}\),求出
\]
其中\(\oplus\)是定义的一种二进制下的运算。
对于这种问题,我们有一种通用的方法,我们称之为\(\text {FWT}\)。
我们考虑对于一个\(A\)构造一个\(FWT\)变换序列,满足:
\]
其中\(\times\)就是上文定义的卷积,\(\star\)是按位乘法。
我们考虑定义一种二进制运算的函数\(c(i,j)\),满足:
\]
于是,我们可以得到:
若存在:
\]
则有:
\]
\]
而我们根据\(FWT\)的定义我们又可以得到:
\]
\]
于是,我们就可以得到:
\]
不过因为是在二进制下的运算,所以一般构造的话都会满足
若
\]
则满足:
\]
于是,我们只需要知道\(c(0/1,0/1)\)即可。
但是,我们现在仅仅可以在\(\Theta(n^2)\)的时间复杂度内求出和转换\(FWT[A]\),显然不能满足我们的对优秀的时间的渴求。
我们想一下在\(\text {FFT}\)中,我们是如何做到\(\Theta(n\log n)\)转换的?分治!!!我们在\(\text {FWT}\)中也可以用类似的方法。
我们考虑对于当前的\(FWT[A]_i\)应该如何求出。
可以得到:
\]
\]
\]
其中\(FWT[A_0/A_1]\)就是子集的一个变换,与\(\text {FFT}\)类似。
我们发现如果我们构造转移矩阵:
\]
其实\(A\to FWT[A]\)每一次变换就是乘上\(\text {mat}\),那么\(FWT[A]\to A\)就是乘上\(\text {mat}\)的逆矩阵。逆矩阵直接手动构造即可。
一些例子
\(\wedge\)
对于并卷积,我们可以构造\(c(i,j)=[i|j]\),其中\([i|j]\)表示的是二进制下的\(i\)是二进制下的\(j\)的子集(每一位\(0/1\)相当于该元素是否在当前集合出现)。
\(\vee\)
对于或卷积,我们可以构造\(c(i,j)=[j|i]\)。
\(\oplus\)
对于异或卷积,我们可以构造\(c(i,j)=(-1)^{|i\wedge j|}\)。
模板题
就是上面三种运算的总和,代码戳这里打开。
非模板的一些例子
\(\text {FST}\)
我们需要解决这样一个问题:
- 给出一个长度为\(n\)的序列\(a_{1,2,...,n},b_{1,2,...,n}\),求出:
\]
对于这个问题,如果没有\(j\wedge k=0\)的话,这就是一个板的\(\text {FWT}\) \(\vee\)运算。我们发现其实\(j\wedge k=0\)的条件就相当于\(|j|+|k|=|j\vee k|\),于是,我们可以设二维数组\(f_i\),我们可以设转移式:
\]
其中\(h_{i,j}=[|j|=i]a_j,w_{i,j}=[|j|=i]b_j\)。
很显然,最后的\(c_i=f_{|i|,i}\)。
于是,我们就可以在\(\Theta(n\log^ 2 n)\)的时间复杂度内解决这个问题。
\(k\)进制下的\(\text {FWT}\)
我们发现上面的这个东西其实都是在\(2\)进制下面计算的,那么如果我们要拓展到\(k\)进制我们应该怎么办呢?
很显然,我们应该定义广义的\(\wedge,\vee,\oplus\)。
- $\wedge $
在\(k\)进制下,定义\(a\wedge b=\min\{a,b\}\)
- \(\vee\)
在\(k\)进制下,定义\(a\vee b=\max\{a,b\}\)
- \(\oplus\)
在\(k\)进制下,定义\(a\oplus b=(a+b)\bmod k\)
因为\(\wedge,\vee\)不是很常用,所以这里着重介绍一下\(\oplus\)。
我们要考虑如何构造\(c(i,j)\),我们发现我们需要满足:
\]
我们在脑中想一下,诶,似乎单位根满足这个条件诶!
于是,我们可以构造矩阵:
\]
而它的逆矩阵就是:
\]
一些例题
随机推荐
- 快速使用 Docker 上手 Sentry-CLI - 玩转 Source Maps 使用 (create-react-app)
系列 快速使用 Docker 上手 Sentry-CLI - 创建版本 入门 使用 sentry-cli 上传 source maps 时,您需要设置构建系统以创建版本(release)并上传与该版本 ...
- Java并发之AQS原理解读(一)
前言 本文简要介绍AQS以及其中两个重要概念:state和Node. AQS 抽象队列同步器AQS是java.util.concurrent.locks包下比较核心的类之一,包括AbstractQue ...
- 基于Linux系统的MariaDB数据库的安装配置
数据库是指长期存储在计算机内.有组织的和可共享的数据集合.表是数据库存储数据的基本单位,一个表由若干个字段组成 MariaDB 数据库管理系统是 MySQL 的一个分支,主要由开源社区在维护,采用 G ...
- zigzag走线原理及应用
电路板上弯弯扭扭的走线有什么用 往期文章: 一文读懂高速互联的阻抗及反射(上) 一文读懂高速互联的阻抗及反射(中) 前面几篇文章有部分读者反馈太深奥,不好懂,要求来一点轻松易懂的.这不,它来了!本期文 ...
- java IO操作,看完你应该就清晰了。
前言: java中IO里的一些知识对于一个java新手来说,是比较难理解的.因为里面存在一些很绕的概念,比如: 1.到底是读入写出,还是读出写入: 2.我要将一个文件的内容拷贝到另一个文件是先用Inp ...
- mybatis动态sql以及分页
1.mybatis动态sql 2.模糊查询 3.查询返回结果集的处理 4.分页查询 5.特殊字符处理 1.mybatis动态sql If.trim.foreach If 标签判断某一字段是否为空 &l ...
- Docker容器管理——Docker容器常用命令
1.查看所有的容器 docker ps 2.查看运行的容器 docker ps -a 3.启动.停止.重启docker容器 docker start ... docker stop ... docke ...
- IMAP协议笔记
1. IMAP客户端接收流程简介 1) 遍历所有的邮箱,获取邮箱状态,然后遍历所有邮箱获取到更新的邮件头部信息(包含收件人.发件人.主题.以及时间信息) 2)获取最新邮件的完整信息,其中也包括在第一步 ...
- Vue指令及自定义指令的使用
导航列表: 一.vue指令 二.自定义指令 一.vue指令 回到顶部 1. v-text v-text主要用来更新textContent,可以等同于JS的text属性,不会解析标签,会把标签解析 ...
- [第一篇]——Docker 教程之Spring Cloud直播商城 b2b2c电子商务技术总结
Docker 教程 Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源. Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然 ...