瞎扯

虽然说是FFT但是还是写了一发NTT(笑)

然后忘了IDFT之后要除个n懵逼了好久

以及递归的时候忘了边界无限RE

思路

朴素算法

分治FFT

考虑到题目要求求这样的一个式子

\[F_x=\Sigma_{i=1}^{x}F_{x-i}G_{i}
\]

我们可以按定义暴力,然后再松式卡常(不是)

我们可以发现它长得像一个卷积一样,但是因为后面的f值会依赖与前面的f值,所以没法一遍FFT直接求出结果,而对每个f都跑一遍FFT太慢了,我们使用分治优化这个过程就很优秀了,复杂度是\(O(n\log^2 n)\)

分治优化

我们能够想到cdq分治的思想,在统计一个区间时,确保对这个区间有影响的操作产生的贡献已经全被统计,就是先统计[l,mid]区间对[mid+1,r]区间的贡献

然后发现对于每个\(f_x\),它对后面的\(f_i\)产生的贡献是\(\Sigma_{j=l}^{mid} f_{i}g_{i-j}\)

然后分治就好

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#define int long long
using namespace std; const int MOD = 998244353,G=3,invG=332748118;
int a[200000],b[200000],f[200000],g[200000],n;
int pow(int a,int b){
int ans=1;
while(b){
if(b&1)
ans=(1LL*ans*a)%MOD;
a=(1LL*a*a)%MOD;
b>>=1;
}
return ans;
}
void FFT(int *a,int opt,int n){
int lim=0;
while((1<<lim)<n)
lim++;
for(int i=0;i<n;i++){
int t=0;
for(int j=0;j<lim;j++)
if((i>>j)&1)
t|=(1<<(lim-j-1));
if(i<t)
swap(a[i],a[t]);
}
for(int i=2;i<=n;i<<=1){
int len=i/2;
int tmp=pow((opt)?G:invG,(MOD-1)/i);
for(int j=0;j<n;j+=i){
int arr=1;
for(int k=j;k<len+j;k++){
int t=arr*a[k+len];
a[k+len]=((a[k]-t)%MOD+MOD)%MOD;
a[k]=(a[k]+t)%MOD;
arr=(arr*tmp)%MOD;
}
}
}
if(opt==0){
int invt=pow(n,MOD-2);
for(int i=0;i<n;i++)
a[i]=a[i]*invt%MOD;
}
}
void solve(int l,int r){
if(r-l==1)
return;
int t=pow(r-l,MOD-2);
int mid=(l+r)>>1;
solve(l,mid);
memset(a+(r-l)/2,0,sizeof(int)*(r-l)/2);
memcpy(a,f+l,sizeof(int)*(r-l)/2);
memcpy(b,g,sizeof(int)*(r-l));
FFT(a,1,r-l);
FFT(b,1,r-l);
for(int i=0;i<r-l;i++)
a[i]=(a[i]*b[i])%MOD;
FFT(a,0,r-l);
for(int i=(r-l)/2;i<r-l;i++)
f[l+i]=(f[l+i]+a[i])%MOD;
solve(mid,r);
}
signed main(){
int mid;
scanf("%lld",&n);
mid=n;
for(int i=1;i<=n-1;i++)
scanf("%lld",&g[i]);
int t=1;
while(t<n)
t<<=1;
n=t;
f[0]=1;
solve(0,n);
for(int i=0;i<mid;i++)
printf("%lld ",f[i]);
return 0;
}

P4721【模板】分治 FFT的更多相关文章

  1. 洛谷 P4721 [模板]分治FFT —— 分治FFT / 多项式求逆

    题目:https://www.luogu.org/problemnew/show/P4721 分治做法,考虑左边对右边的贡献即可: 注意最大用到的 a 的项也不过是 a[r-l] ,所以 NTT 可以 ...

  2. 洛谷.4721.[模板]分治FFT(NTT)

    题目链接 换一下形式:\[f_i=\sum_{j=0}^{i-1}f_jg_{i-j}\] 然后就是分治FFT模板了\[f_{i,i\in[mid+1,r]}=\sum_{j=l}^{mid}f_jg ...

  3. 解题:洛谷4721 [模板]分治FFT

    题面 这是CDQ入门题,不要被题目名骗了,这核心根本不在不在FFT上啊=.= 因为后面的项的计算依赖于前面的项,不能直接FFT.所以用CDQ的思想,算出前面然后考虑给后面的贡献 #include< ...

  4. 洛谷 P4721 【模板】分治 FFT 解题报告

    P4721 [模板]分治 FFT 题目背景 也可用多项式求逆解决. 题目描述 给定长度为 \(n−1\) 的数组 \(g[1],g[2],\dots,g[n-1]\),求 \(f[0],f[1],\d ...

  5. [洛谷P4721]【模板】分治 FFT

    题目大意:给定长度为$n-1$的数组$g_{[1,n)}$,求$f_{[0,n)}$,要求: $$f_i=\sum_{j=1}^if_{i-j}g_j\\f_0=1$$ 题解:直接求复杂度是$O(n^ ...

  6. 洛谷P4721 【模板】分治 FFT(分治FFT)

    传送门 多项式求逆的解法看这里 我们考虑用分治 假设现在已经求出了$[l,mid]$的答案,要计算他们对$[mid+1,r]$的答案的影响 那么对右边部分的点$f_x$的影响就是$f_x+=\sum_ ...

  7. 洛谷P4721 【模板】分治 FFT(生成函数+多项式求逆)

    传送门 我是用多项式求逆做的因为分治FFT看不懂…… upd:分治FFT的看这里 话说这个万恶的生成函数到底是什么东西…… 我们令$F(x)=\sum_{i=0}^\infty f_ix^i,G(x) ...

  8. [题解] Luogu P4721 【模板】分治 FFT

    分治FFT的板子为什么要求逆呢 传送门 这个想法有点\(cdq\)啊,就是考虑分治,在算一段区间的时候,我们把他分成两个一样的区间,然后先做左区间的,算完过后把左区间和\(g\)卷积一下,这样就可以算 ...

  9. luoguP4721 【模板】分治 FFT

    P4721 [模板]分治 FFT 链接 luogu 题目描述 给定长度为 \(n-1\) 的数组 \(g[1],g[2],..,g[n-1]\),求 \(f[0],f[1],..,f[n-1]\),其 ...

随机推荐

  1. JavaScript中直接量和变量

    标题 1.直接量 顾名思义,可以直接拿来使用的量.那哪些是直接量呢?数据类型又有很多种,因为不同类型的数据处理方式是不同的,所以数据要分类型 基本类型 1.1 String字符串 用单引号或双引号引起 ...

  2. Swift 了解(3)

    类(Classes) 假设你是一个建筑师,你刚刚签了一个合同,要在一个新的小区修建20个相似的房子.在你派出建筑工队之前,你必须要画一个房子的设计图.这份设计图将会展现房子的外表和功能.把这份设计图当 ...

  3. 邮件服务器hMailServer管理工具hMailServer Administrator汉化(转)

    //实现:邮件服务器hMailServer管理工具hMailServer Administrator的汉化 //环境: Windows Server 2008 R2 hMailServer Admin ...

  4. 集合——iterator迭代器

    Iterator接口: Iterator接口使用: 其中,集合Collection接口的定义也是使用多态,必须要创建它的子类对象才行,子类接口也是不能直接创建对象的(List接口): 其中wihle的 ...

  5. js异步计时器

    js中同步和异步的区别: 1.同步会阻塞代码执行,而异步不会 2.alert 是同步,setTimeout 是异步 何时需要异步 1.在可能发生等待的情况 2.等待过程中不能像 alert 一样阻塞程 ...

  6. python练习:一行搞定-统计一句话中每个单词出现的个数

    一行搞定-统计一句话中每个单词出现的个数 >>> s'i am a boy a bood boy a bad boy' 方式一:>>> dict([(i,s.spl ...

  7. 收音机FM和AM的区别

    1.频率区别 FM = Frequency Modulation 调频,微波:微波传输,信号质量高,传输成本低,发射功率小,覆盖范围小,受地理因素影响较大,一般作为城市广播的首选.比如你的家乡城市台, ...

  8. flask框架----蓝图

    蓝图(flask中多py文件拆分都要用到蓝图) 如果代码非常多,要进行归类.不同的功能放在不同的文件,吧相关的视图函数也放进去.蓝图也就是对flask的目录结构进行分配(应用于小,中型的程序), 小中 ...

  9. glog日志库移植Android平台

    1.在linux平台下使用ndk交叉编译链编译glog生成libglog.a静态库. 2.将生成的库文件与头文件放到Android项目中,使用JNI方法调用. 3.编译遇到错误“stderr.stdo ...

  10. shell 中的小技巧

    去掉最后一个字符 sed 's/.$//' awk '{sub(/.$/,"")}1' awk '{printf $0"\b \n"}' [root@ ~]# ...