一般的分治FFT是指:

https://www.luogu.org/problemnew/show/P4721

考虑后面的f和前面的f有关系,但是贡献可以分着计算,逐一累计上去。

考虑cdq分治。算出前面的[1,mid]的f之后,可以直接一次NTT,把后面[mid+1,r]的f的一部分算出来,累加上去。

对于后面的部分,发现都是一个前缀没有计算上。继续分治下去即可。

画个图就是这样。

细节注意:

1.边界,

2.0~n-1

3.四倍N的数组

4.注意之后每次都是NTT一个前缀。

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define numb (ch^'0')
#define int long long
using namespace std;
typedef long long ll;
il void rd(int &x){
char ch;x=;bool fl=false;
while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);
(fl==true)&&(x=-x);
}
namespace Miracle{
const int N=1e5+;
const int mod=;
const int G=;
const int GI=;
int n,m;
ll qm(ll x,ll y){
ll ret=;
while(y){
if(y&) ret=ret*x%mod;
x=x*x%mod;
y>>=;
}
return ret;
}
int rev[*N];
void fft(int *a,int n,int c){
for(reg i=;i<=n-;++i){
if(i<rev[i]) swap(a[i],a[rev[i]]);
}
for(reg p=;p<=n;p<<=){
ll gen;
if(c==) gen=qm(G,(mod-)/p);
else gen=qm(GI,(mod-)/p);
for(reg l=;l<n;l+=p){
ll lp=;
for(reg k=l;k<l+p/;++k){
ll tmp=a[k+p/];
a[k+p/]=(a[k]-tmp*lp%mod+mod)%mod;
a[k]=(a[k]+tmp*lp%mod)%mod;
lp=lp*gen%mod;
}
}
}
} ll g[*N],f[*N],c[*N],d[*N];
void calc(int *a,int *b,int n){
for(reg i=;i<n;++i){
rev[i]=(rev[i>>]>>)|((i&)?n>>:);
}
fft(a,n,);fft(b,n,);
for(reg i=;i<n;++i) b[i]=a[i]*b[i]%mod;
fft(b,n,-);
ll inv=qm(n,mod-);
for(reg i=;i<n;++i) b[i]=b[i]*inv%mod;
}
void divi(int l,int r,int L,int R){
//cout<<" divi "<<l<<" "<<r<<" and "<<L<<" "<<R<<endl;
if(l==r){
return;
}
int mid=(l+r)>>;
int Md=(L+R)>>;
divi(l,mid,L,Md); //cout<<" bac to "<<l<<" "<<r<<endl;
for(reg i=l;i<=mid;++i) c[i-l]=f[i];
for(reg i=mid+;i<=r;++i) c[i-l]=;
for(reg i=L;i<=R;++i) d[i-L]=g[i];
for(reg i=r-l+;i<=(r-l+)*-;++i) c[i]=d[i]=;
calc(c,d,(r-l+)*);
for(reg i=mid+;i<=r;++i) f[i]=(f[i]+d[i-l])%mod;
//cout<<" f[4] "<<f[4]<<" f[5] "<<f[5]<<endl; divi(mid+,r,L,Md);
}
int main(){
rd(n);
int lp=n;
for(reg i=;i<n;++i) rd(g[i]);
g[]=;f[]=;
for(m=n,n=;n<m;n<<=);
divi(,n-,,n-);
for(reg i=;i<lp;++i){
printf("%lld ",f[i]);
}
return ;
} }
signed main(){
Miracle::main();
return ;
} /*
Author: *Miracle*
Date: 2018/12/21 14:08:16
*/

配赠福利:

一、

升级版:真的分治fft(这个代码我觉得如果有l>=r-l+1,那么可以直接return掉,后面[l,mid]*[l,mid]没有意义。)

现在的g变成了f,直接刚才那样cdq,会出现一些mid+1~r区间的f还要贡献,但是我们目前没有计算出来

还是考虑cdq分治

假设计算出来了[l,mid],那么,先把[l,mid]*[l,mid]的多项式的贡献计算出来

剩下没有算出来的怎么补?

每个值剩下的没有计算的部分,其右部分没有被计算到的区间,一定是一个l>=r-l+1的区间

如果有l>=r-l+1,那么把f[0,r-l]*f[l,mid]再计算一下,然后*2(其实本质上是补全第一次乘漏的部分)

是一种延迟处理的方法,因为先算的话,有一半没有计算出来;而反过来再算的时候,涉及到的f就已经都算完了。恰好,两边对称,所以*2解决。

二、

分治FFT字面意思理解一下的话,,就是分治+FFT。。。

所以,如果要计算:

(x+a)*(x+b)*(x+c)*(x+d)*....

直接暴力算的复杂度是(2+3+4+...n)*logn

分治的话,每个(x+a)贡献的是2的长度,,一共贡献logn次,所以O(nlog^2n)

[学习笔记]分治FFT的更多相关文章

  1. 「学习笔记」FFT 快速傅里叶变换

    目录 「学习笔记」FFT 快速傅里叶变换 啥是 FFT 呀?它可以干什么? 必备芝士 点值表示 复数 傅立叶正变换 傅里叶逆变换 FFT 的代码实现 还会有的 NTT 和三模数 NTT... 「学习笔 ...

  2. 「学习笔记」FFT 之优化——NTT

    目录 「学习笔记」FFT 之优化--NTT 前言 引入 快速数论变换--NTT 一些引申问题及解决方法 三模数 NTT 拆系数 FFT (MTT) 「学习笔记」FFT 之优化--NTT 前言 \(NT ...

  3. 快速傅里叶变换学习笔记(FFT)

    什么是FFT FFT是用来快速计算两个多项式相乘的一种算法. 如果我们暴力计算两个多项式相乘,复杂度必然是\(O(n^2)\)的,而FFT可以将复杂度降至\(O(nlogn)\) 如何FFT 要学习F ...

  4. 「学习笔记」FFT及NTT入门知识

    前言 快速傅里叶变换(\(\text{Fast Fourier Transform,FFT}\) )是一种能在\(O(n \log n)\)的时间内完成多项式乘法的算法,在\(OI\)中的应用很多,是 ...

  5. 【学习笔记】FFT

    1.内容 由于noble_太懒 不想写了 非常好的博客: https://www.cnblogs.com/rvalue/p/7351400.html http://www.cnblogs.com/ca ...

  6. 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT)

    再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT) 目录 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Blueste ...

  7. 分治 FFT学习笔记

    先给一道luogu板子题:P4721 [模板]分治 FFT 今天模拟有道题的部分分做法是分治fft,于是就学了一下.感觉不是很难,国赛上如果推出式子的话应该能写出来. 分治fft用来解决这么一个式子\ ...

  8. 分治FFT学习笔记

    用途 在\(O(n\log^2 n)\)的时间内做诸如 \[ f_n=\sum_{i=0}^{n-1} f_ig_{n-i} \] 或是 \[ f_n=\sum_{i=0}^{n-1} f_if_{n ...

  9. 多项式求逆/分治FFT 学习笔记

    一.多项式求逆 给定一个多项式 \(F(x)\),请求出一个多项式 \(G(x)\), 满足 \(F(x) * G(x) \equiv 1 ( \mathrm{mod\:} x^n )\).系数对 \ ...

随机推荐

  1. DEDEcms调用当前栏目顶级栏目url地址

    include/common.func.php 找到这个文件 在文件最下方加入以下代码: //获取顶级栏目url function GetTopTypeurl($id) { global $dsql; ...

  2. Windowserver2012部署always on

    1.首先,安装域环境 IP设置 域服务安装 如果建立域配置时出现 administrator账户密码不符合要求错误: cmd运行命令: net user administrator /password ...

  3. Windows如何设置动态和静态ip地址

    打开控制面板,一般在电脑的菜单栏能找到,win8和win10可以使用快捷键(win键+X键),找不到的朋友可以搜索一下.   进入到网络和共享中心,点击更改适配器设置.   这里显示的是电脑所以的网络 ...

  4. TPO-14 C1 Locate a political book

    TPO-14 C1 Locate a political book 第 1 段 1.Listen to a conversation between the student and librarian ...

  5. 第3章 TCP协议详解

    第3章 TCP协议详解 3.1 TCP服务的特点 传输协议主要有两个:TCP协议和UDP协议,TCP协议相对于UDP协议的特点是 面向连接使用TCP协议通信的双方必须先建立连接,完成数据交换后,通信双 ...

  6. hadoop3.0新特性及新功能

    Hadoop-3.0.0-alpha2版本发布,相比之前的hadoop-2.x有一系列的功能增强.但目前还是个alpha版本,有很多bug,且不能保证API的稳定和质量. 主要变化 Java最低版本要 ...

  7. 【Linux 运维】 安装PHP工具Composer

    一.安装PHP 由于Composer是 PHP 用来管理依赖(dependency)关系的工具.你可以在自己的项目中声明所依赖的外部工具库(libraries),Composer 会帮你安装这些依赖的 ...

  8. Python的实现分类

    目前流行的Python实现包括CPython,Jython,IronPython,Stackless,PyPy,Cython,Shed Skin. CPython Cpython是Python的标准实 ...

  9. LintCode-71.二叉树的锯齿形层次遍历

    二叉树的锯齿形层次遍历 给出一棵二叉树,返回其节点值的锯齿形层次遍历(先从左往右,下一层再从右往左,层与层之间交替进行) 样例 给出一棵二叉树 {3,9,20,#,#,15,7}, 返回其锯齿形的层次 ...

  10. PAT 甲级 1048 Find Coins

    https://pintia.cn/problem-sets/994805342720868352/problems/994805432256675840 Eva loves to collect c ...