FFT与NTT专题
先不管旋转操作,考虑化简这个差异值
$$
begin{aligned}
sum_{i=1}^n(x_i-y_i-c)^2
&=sum_{i=1}^n(x_i-y_i)^2+nc^2-2csum_{i=1}^n(x_i-y_i)\
&=sum_{i=1}^nx_i^2+sum_{i=1}^ny_i^2+nc^2-2csum_{i=1}^n(x_i-y_i)-2sum_{i=1}^nx_iy_i
end{aligned}
$$
注意到$sum x^2+sum y^2$是常数,先不管
可以发现,这是一个关于$c$的二次函数
那么我们知道,此时$c$的极值点就在$-frac{b}{2a}$处
所以,我们可以得出$c$的最优值是
$$
frac{sum_{i=1}^n x_i-sum_{i=1}^n y_i}{n}
$$
而分子的两个数均与旋转无关
但是$c$只能是整数
所以判一下$c, c-1, c+1$哪个与上面的式子更接近
注意到旋转唯一能改变的是$sum xy$
而我们要让这个值尽量小
设
$$
F(m)=sum_{i=1}^nx_iy_{i+m}
$$
我们可以看出,这是一个类似卷积的东西
但是一般的卷积是后两式下标的和不变
而这个是差不变
所以把这个式子变一下
设
$$
x_{n-i+1}=x_i
$$
就是将x倒序一下
可以得到
$$
F(m)=sum_{i=1}^nx_{n-i+1}y_{i+m}
$$
不妨设后面$xy$的卷积是$A$,也就是
$$
A(n+m+1)=sum_{i=1}^nx_{n-i+1}y_{i+m}
$$
可以发现,这个$A$就是将$F$整体向右平移了$n+1$
所以
$$
F(m)=A(n+m+1)
$$
为了不丢精度,NTT即可(保证答案不会超过mod)
代码如下
1 |
using namespace std; |
B – 求和
我们知道
$$
S(n,m)=sum_{i=0}^m(-1)^i{mchoose i}(m-i)^nfrac{1}{m!}
$$
原理很简单,容斥有几个盒子没有放球,有$mchoose i$种选法,再将$n$个球放入$m-i$个盒子。由于盒子是无序的,最后除以$m$的阶乘
那么我们用这个化简原式
注意到第二个$sum$的上界是$i$,非常讨厌
由于斯特林数的性质,把这个$i$换成$n$也没有问题
因为当$m>n$时,$S(n,m)=0$
所以有
$$
begin{aligned}
sum_{i=0}^nsum_{j=0}^nS(i,j)*2^j*j!
&=sum_{j=0}^n2^j*j!sum_{i=0}^nsum_{k=0}^j(-1)^k{jchoose k}(j-k)^ifrac{1}{j!}\
&=sum_{j=0}^n2^j*j!sum_{k=0}^jfrac{(-1)^k}{k!}*frac{sum_{i=0}^n(j-k)^i}{(j-k)!}
end{aligned}
$$
注意到后面那个是卷积的形式
第一个多项式很好求,第二个的分子是等比数列
我们设$B$是第二个多项式
显然有
$$
B(0)=0, B(1)=n+1
$$
对于其它情况,直接用等比数列求和公式算出来就行了
代码如下
1 |
using namespace std; |
C – 序列统计
这题的难点在于转化成原根
注意到要求的是所有数的乘积而非和
如果是和的话直接NTT就好了
那么我们就将乘积转化成和的形式
如果两个数都是某个数的某次方,那么这两个数乘起来就是指数相加
而原根恰好可以表示模$m$剩余系下的每个数
所以把每个数转化成原根的某次方就好了
求原根代码
1 |
inline int G(int x) {
|
D – 残缺的字符串
带通配符的字符串匹配问题
首先考虑不带通配符的怎么做
那么拓展KMP, 后缀数组都可以
但是我们有一个更高级的方法:FFT求字符串匹配
首先我们需要定义“匹配”
所以设差异函数$g(i)$表示从$B$串的$i$位置开始,与$A$串的差异程度
有
$$
g(x)=sum_{i=x}^{x+m-1}(B_i-A_{i-x+1})^2
$$
显然,只有当$A$串从$x$位置开始与$B$串完全相同,$g$的值才为0
化简原式
$$
begin{aligned}
g(x)&=sum_{i=x}^{x+m-1}A_{i-x+1}^2+sum_{i=x}^{x+m-1}B_i^2-2sum_{i=x}^{x+m-1}B_iA_{i-x+1}\
&=sum_{i=1}^mA_i^2+sum_{i=1}^mB_{i+x-1}^2-2sum_{i=1}^mA_iB_{i+x-1}
end{aligned}
$$
前两项可以通过预处理前缀和得出,后面的是一个下标差相等的卷积
那么模仿之前的套路,我们将$A$序列倒序一下再求卷积就行了
解决了不带通配符的问题,再考虑带通配符
这个通配符是可以匹配任意字符的,所以把差异函数改一下
$$
g(x)=sum_{i=x}^{x+m-1}(B_i-A_{i-x+1})^2A_{i-x+1}B_i
$$
当$i$处的字符是$*$时,我们设那个地方的值为0
化简得
$$
=sum_{i=1}^mA_i^3B_{i-x+1}+sum_{i=1}^mA_iB_{i-x+1}^3-2sum_{i=1}^xA_i^2B_{i-x+1}^2
$$
做3次FFT即可
代码如下
1 |
using namespace std; |
E – 万径人踪灭
假设当前确定了一个对称中心$i$
那么当两个位置$j,k$关于i对称且这两个位置的字母相同时对答案有贡献
对称则意味着$j+k=i*2$,可以FFT
枚举字符,然后FFT
假设这个中心有x对这样的位置
那么每一对都是独立的,可以选也可以不选,但是不能都不选
所以此时的答案为$2^x-1$
题目要求不能全部连续,那么最后再跑一边manacher,减去全部连续的答案即可
代码如下
1 |
using 大专栏 FFT与NTT专题s="keyword">namespace std; |
F – 性能优化
这道题利用到了FFT的原理
如果模数是质数,那么非常好办
但是这题不仅模数不是质数,而且求的是循环卷积,直接FFT会爆炸
贴一篇我觉得很好的题解

这个rev数组可以模拟FFT的过程,递归地求出来
单位根满足消去律,上面的$F(omega_n^i)$指的是$ileq frac{n}{p}$的情况
对于剩余的情况,有$omega_{frac{n}{p}}^i=omega_{frac{n}{p}}^{i-frac{n}{p}}$
也就是说,代入的$F^{[0]},F^{[1]},cdots,F^{[p-1]}$都相同,但是系数不同
然后分治就可以了
同样地,最后需要除以len,也就是模数$-1$
代码如下
1 |
using namespace std; |
H – Frightful Formula
算是比较简单的一道题
公式等价于一个表格,往右走有$a$种方法,往下走有$b$种方法,还可以直接从这个格子开始走,有$c$种方法
先不考虑第一行和第一列格子
假设是从$i,j$这个格子开始走的
那么,这个格子需要向右走$n-j$步,向下走$n-i$步
对答案的贡献是
$$
c*a^{n-i}*b^{n-j}*{n-i+n-jchoose n-i}
$$
含义是,从这个格子开始,有$c$种走法,向有走$n-j$次,向下走$n-i$次,在$n-j+n-i$步中,有$n-i$步是往下走的
那么,把这些空白的格子加起来,我们可以得到
$$
begin{aligned}
csum_{i=2}^nsum_{j=2}^na^{n-i}b^{n-j}{n-i+n-jchoose n-i}
&=csum_{i=0}^{n-2}sum_{j=0}^{n-2}a^ib^j{i+jchoose i}\
&=csum_{i=0}^{n-2}frac{a^i}{i!}sum_{j=0}^{n-2}(i+j)!frac{b^j}{j!}
end{aligned}
$$
我们可以枚举$i$,后面的是一个下标差相等的卷积
将多项式逆序一下就可以了
这道题没有给模数,而答案又很大
为了防止丢精度,所以使用MTT
代码如下
1 |
#include <bits/stdc++.h> |
FFT与NTT专题的更多相关文章
- FFT,NTT 专题
学习傅里叶的基本性质及其代码,可以参考大神理解 还有 ACdream 的博客 贴一下NTT的模板: using namespace std; typedef long long ll; int n; ...
- 多项式fft、ntt、fwt 总结
做了四五天的专题,但是并没有刷下多少题.可能一开始就对多项式这块十分困扰,很多细节理解不深. 最简单的形式就是直接两个多项式相乘,也就是多项式卷积,式子是$N^2$的.多项式算法的过程就是把卷积做一种 ...
- 多项式乘法,FFT与NTT
多项式: 多项式?不会 多项式加法: 同类项系数相加: 多项式乘法: A*B=C $A=a_0x^0+a_1x^1+a_2x^2+...+a_ix^i+...+a_{n-1}x^{n-1}$ $B=b ...
- FFT和NTT学习笔记_基础
FFT和NTT学习笔记 算法导论 参考(贺) http://picks.logdown.com/posts/177631-fast-fourier-transform https://blog.csd ...
- fft,ntt总结
一个套路:把式子推成卷积形式,然后用fft或ntt优化求解过程. fft的扩展性不强,不可以在fft函数里多加骚操作--DeepinC T1:多项式乘法 板子题 T2:快速傅立叶之二 另一个板子,小技 ...
- 卷积FFT、NTT、FWT
先简短几句话说说FFT.... 多项式可用系数和点值表示,n个点可确定一个次数小于n的多项式. 多项式乘积为 f(x)*g(x),显然若已知f(x), g(x)的点值,O(n)可求得多项式乘积的点值. ...
- 多项式的基本运算(FFT和NTT)总结
设参与运算的多项式最高次数是n,那么多项式的加法,减法显然可以在O(n)时间内计算. 所以我们关心的是两个多项式的乘积.朴素的方法需要O(n^2)时间,并不够优秀. 考虑优化. 多项式乘积 方案一:分 ...
- 浅谈FFT、NTT和MTT
前言 \(\text{FFT}\)(快速傅里叶变换)是 \(O(n\log n)\) 解决多项式乘法的一个算法,\(\text{NTT}\)(快速数论变换)则是在模域下的,而 \(\text{MTT} ...
- hdu 1402(FFT乘法 || NTT乘法)
A * B Problem Plus Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Other ...
随机推荐
- vscode显示当前文件完整路径信息
Code->Preferences->Settings 搜索window.title 原本是activeEditorShort,修改 activeEditorShort => act ...
- 申请FreeDomain,透过DNS转回自己的Godaddy Cpanel
148.66.136.216这个IP,是我的Cpanel IP. 过了几分钟,这个kkchan.tk就转到Cpanel了. 然后在Cpanel的Addon Domains加上kkchan.tk,那就可 ...
- Java Keyword Synchronized 学习记录
Synchronized Java编程思想:每个对象都包含了一把锁(也叫作"监视器"),它自动成为对象的一部分,调用任何synchronized方法时,对象就会被锁定,不可再调用那 ...
- php抓取网站图片源码
<?php /*完成网页内容捕获功能*/ function get_img_url($site_name){ $site_fd = fopen($site_name, "r&q ...
- BitcoinCore JSONRPC Java使用,创建账号,获取余额,转账等等...
1.首先要安装好bitcoin core服务 上一篇有怎么安装 下面代码支持多钱包多地址动态调用,但让我没用使用多地址,根据自己的需要然后封装方法就好 2.引入jar JavaBitcoinRpcC ...
- Python模块——hashlib
简介 hashlib模块是用于对字符串进行加密,其可以把任意长度的数据转换为一个长度固定的数据串,且这种加密是不可逆的,故这种加密方式的安全性都很高.hash本质是一个函数,该模块提供了许多不同的加密 ...
- 哈夫曼编码的理解(Huffman Coding)
哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,可变字长编码(VLC)的一种.Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最 ...
- idea远程调试tomcat部署项目(windows环境)
1.tomcat启动之前,修改apache-tomcat-8.5.34\bin\catalina.bat文件,设置调试端口 如下设置(windows环境): rem ----------------- ...
- springMVC的注解@PathVariable是什么?详情及用法解析
在路由中定义变量规则后,通常我们需要在处理方法(也就是@RequestMapping注解的方法)中获取这个URL变量的具体值,并根据这个值(例如用户名)做相应的操作,Spring MVC提供的@Pat ...
- Qt QPixmap和QImage的相互转换
QPixmap转为Image: QPixmap pixmap; pixmap.load("../Image/1.jpg"); QImage tempImage = pixmap.t ...