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 ...
随机推荐
- Java if、switch语句,break,case,类型转换、常量、赋值比较、标识符(2)
if语句: /* if else 结构 简写格式: 变量 = (条件表达式)?表达式1:表达式2: 三元运算符: 好处:可以简化if else代码. 弊端:因为是一个运算符,所以运算完必须要有一个结果 ...
- CodeForces 1287B Hyperset
N^2遍历所有得(i,j)然后可以根据(i,j)字符串构造出来第三个T字符串,然后查找一下是否有这个T存在即可,注意最后答案要/3因为会重复出现. #include <stdio.h> # ...
- PAT Advanced 1138 Postorder Traversal (25) [树的遍历,前序中序转后序]
题目 Suppose that all the keys in a binary tree are distinct positive integers. Given the preorder and ...
- 独立t检验
方差相同个数相同的独立t检验 5.某饲料厂要比较A.B两种配合饲料在养猪生产中的效果,选取12头情况相似的猪,随机分成两组,分别饲喂两种配合饲料,其60天增重(单位:kg)见下表. 饲 料 60d增重 ...
- ZJNU 1164 - 考试排名——中级
1.如果一个单元为0,表示没做过这题,不计入成绩 2.如果一个单位为负数,表示做错了这题,不计入成绩 所以只要一个单元为正数(不论是否有括号)都说明做出了这一题,计入成绩 将名字和成绩都当作字符串读入 ...
- linux xargs详解
xargs [-0prtx] [-E eof-str] [-e[eof-str]] [--eof[=eof-str]] [--null] [-d delimiter] [--delimiter d ...
- MplayerX 安装
从老的笔记本中,把MplayerX.app 复制到新笔记本并放到应用程序目录中,可以直接用. 但播放时出现花屏,百度得到原因是新的硬件加速不支持, 解决办法是,在偏好设置-> 高级 -> ...
- CaptchaCodeManager
package org.linlinjava.litemall.wx.service; import org.linlinjava.litemall.wx.dto.CaptchaItem; impor ...
- 01 语言基础+高级:1-7 异常与多线程_day05 【异常、线程】
day05 [异常.线程] 主要内容 异常.线程 教学目标 能够辨别程序中异常和错误的区别 说出异常的分类 说出虚拟机处理异常的方式 列举出常见的三个运行期异常 能够使用try...catch关键字处 ...
- 实现hashmap
/**数组下面挂着链表*/ #include<stdio.h> #include<unistd.h> #include<stdlib.h> #include< ...