快速莫比乌斯变换(FMT)
快速莫比乌斯变换(FMT)
原文出处:虞大的博客。此仅作蒟蒻本人复习用~
给定两个长度为n的序列 \(a_0, a_1, \cdots, a_{n-1}\)和\(b_0, b_1, \cdots, b_{n-1}\),你需要求出一个序列\(c_0, c_1, \cdots, c_{n-1}\),其中\(c_k\)满足:\(c_k = \sum\limits_{i \mid j = k} a_i b_j\)。其中|表示按位或。\(n \leq 10^6\)表示序列长度。
显然发现\(i∣j=k\)这个条件不怎么好处理,如果我们作一个集合的 "前缀和" ,即令\(P_i = \sum\limits_{j \subseteq i} p_j\)(\(i\&j=j\)),那么有:\(C_k = \sum_{k_0 \subseteq k} c_i = \sum_{k_0 \subseteq k} \sum_{i \cup j = k_0} a_i b_j = \sum_{i \cup j \subseteq k} a_i b_j = \left( \sum_{i \subseteq k} a_i \right) \left( \sum_{j \subseteq k} b_j \right) = A_k \cdot B_k\)
所以说我们就把集合并卷积转化成了两个“前缀和”集合的\(O(n)\)运算,和FFT差不多。现在的问题就是怎么快速算出这些“前缀和”集合。
我们可以画一张图,图中每一行代表一个\(P_i\)。这一行有哪些格子涂蓝,就代表它是哪些\(p_i\)的和:
如果用动态规划来理解的话,令\(f[i][j]\)表示j的开头\(2^i\)个数中为权值为1的数的和, 那么转移显然就是\(f[i+1][j+2^i]+=f[i][j]\)(j的\(2^i\)位是0)。其中j这一维是可以压掉的。
如果改变一下你脑海中的求和顺序,那么循环内的一次加法,就相当于一个集合的前面2^i个元素的值被加上了。
如果要把\(f\)还原该怎么办呢?只要把+=改成-=就行了~(不会证,但是真的很好记)
#include <cctype>
#include <cstdio>
using namespace std;
typedef long long LL;
const LL maxn=2e6+5;
LL n, l, bits, a[maxn], b[maxn], c[maxn];
void FMT(LL *f, LL flag){
for (LL i=0; i<bits; ++i)
for (LL j=0; j<l; ++j)
if ((j>>i&1)==0) f[j|1<<i]+=(~flag?f[j]:-f[j]);
}
inline void getint(LL &x){
char ch; x=0;
for (; ch=getchar(), !isdigit(ch););
for (x=ch-48; ch=getchar(), isdigit(ch);)
x=(x<<3)+(x<<1)+ch-48;
}
int main(){
getint(n); l=1;
while (l<n) l<<=1, ++bits;
for (LL i=0; i<n; ++i) getint(a[i]); FMT(a, 1);
for (LL i=0; i<n; ++i) getint(b[i]); FMT(b, 1);
for (LL i=0; i<l; ++i) c[i]=a[i]*b[i]; FMT(c, -1);
//坑点1:乘法可能爆LL 坑点二:i要到l
for (LL i=0; i<n; ++i) printf("%lld ", c[i]);
return 0;
}
快速莫比乌斯变换(FMT)的更多相关文章
- 集合并卷积的三种求法(分治乘法,快速莫比乌斯变换(FMT),快速沃尔什变换(FWT))
也许更好的阅读体验 本文主要内容是对武汉市第二中学吕凯风同学的论文<集合幂级数的性质与应用及其快速算法>的理解 定义 集合幂级数 为了更方便的研究集合的卷积,引入集合幂级数的概念 集合幂级 ...
- 快速沃尔什变换(FWT) 与 快速莫比乌斯变换 与 快速沃尔什变换公式推导
后面的图片将会告诉: 如何推出FWT的公式tf 如何推出FWT的逆公式utf 用的是设系数,求系数的方法! ============================================== ...
- 快速沃尔什变换&快速莫比乌斯变换小记
u1s1 距离省选只剩 5 days 了,现在学新算法真的合适吗(( 位运算卷积 众所周知,对于最普通的卷积 \(c_i=\sum\limits_{j+k=i}a_jb_k\),\(a_jb_k\) ...
- P4717-[模板]快速莫比乌斯/沃尔什变换(FMT/FWT)
正题 题目链接:https://www.luogu.com.cn/problem/P4717 题目大意 给出两个长度为\(2^n\)的数列\(A,B\)求 \[C_{n}=\sum_{i\ or\ j ...
- BZOJ 4036: [HAOI2015]按位或 集合幂函数 莫比乌斯变换 莫比乌斯反演
http://www.lydsy.com/JudgeOnline/problem.php?id=4036 http://blog.csdn.net/lych_cys/article/details/5 ...
- 为什么要进行傅立叶变换?傅立叶变换究竟有何意义?如何用Matlab实现快速傅立叶变换
写在最前面:本文是我阅读了多篇相关文章后对它们进行分析重组整合而得,绝大部分内容非我所原创.在此向多位原创作者致敬!!!一.傅立叶变换的由来关于傅立叶变换,无论是书本还是在网上可以很容易找到关于傅立叶 ...
- 离散傅立叶变换与快速傅立叶变换(DFT与FFT)
自从去年下半年接触三维重构以来,听得最多的词就是傅立叶变换,后来了解到这个变换在图像处理里面也是重点中的重点. 本身自己基于高数知识的理解是傅立叶变换是将一个函数变为一堆正余弦函数的和的变换.而图像处 ...
- 快速傅里叶变换 & 快速数论变换
快速傅里叶变换 & 快速数论变换 [update 3.29.2017] 前言 2月10日初学,记得那时好像是正月十五放假那一天 当时写了手写版的笔记 过去近50天差不多忘光了,于是复习一下,具 ...
- 快速傅立叶变换(FFT)算法
已知多项式f(x)=a0+a1x+a2x2+...+am-1xm-1, g(x)=b0+b1x+b2x2+...+bn-1xn-1.利用卷积的蛮力算法,得到h(x)=f(x)g(x),这一过程的时间复 ...
随机推荐
- Java学习之系统高可用性渲染接口日志自动服务降级
背景:公司都追求系统的高可用性,这里不可用时间就是其中很重要的一个指标,为此在做系统功能升级迭代的过程中如何快速处理异常恢复正常功能极为重要.现在对新增模块的要求是都增加开关,方便快速关闭异常模块,但 ...
- 自定义ASP.NET MVC Html辅助方法
在ASP.NET MVC中,Html辅助方法给我们程序员带来很多方便,其重要性也就不言自明.有时候,我们不想重复地写一些HTML代码,或者MS没有提供我们想要的那个HTML标签的Html辅助方法,那么 ...
- 50 states of America
美国州名 州名英文 州名音标 简写 首府 首府 阿拉巴马州 Alabama [ˌæləˈbæmə] AL 蒙哥马利 Montgomery[mənt'gʌməri] 阿拉斯加州 Alaska [ ...
- Ubuntu bash不记录history方法
很多都是用: unset HISTORY HISTFILE HISTSAVE HISTZONE HISTORY HISTLOG export HISTFILE=/dev/null export HIS ...
- PHP实现常用排序算法(含示意动图)
目录 1 快速排序 2 冒泡排序 3 插入排序 4 选择排序 5 归并排序 6 堆排序 7 希尔排序 8 基数排序 总结 作为phper,一般接触算法的编程不多. 但基本的排序算法还是应该掌握. 毕竟 ...
- 2016上海浦东汽车展览会C+罩杯 车模名单
只能帮你们到这了
- VS调试程序时,程序出现异常,但VS不报错的解决方案
在调试>异常> 里面把勾全勾上就行了!
- 数据存储的两种方式:Cookie 和Web Storage(转)
数据存储的两种方式:Cookie 和Web Storage 数据存储的两种方式:Cookie 和Web Storage 1.Cookie Cookie的作用就像你去超市购物时,第一次给你办张购物卡 ...
- go语言的源码文件的分类及含义
Go源码文件:名称以.go为后缀,内容以Go语言代码组织的文件 多个Go源码文件是需要用代码包组织起来的 源码文件分为三类:命令源码文件.库源码文件(go语言程序) 测试源码文件(辅助源码文件) 命令 ...
- css 层叠式样式表(2)
一,样式表分类 (1)内联样式. --优先级最高,代码重复使用最差. (当特殊的样式需要应用到单独某个元素时,可以使用. 直接在相关的标签中使用样式属性.样式属性可以包含任何 CSS 属性.) (2) ...