为啥要叫分治\(fft\)啊,又用不到\(fft……\)

给定长度为\(n-1\)的数组\(g[1],g[2],……,g[n-1]\),求\(f[1],f[2],……,f[n]\),其中

\[f[i]=\sum\limits_{j=1}^{i}f[j-i]g[j]
\]

边界为\(f[0]=1\),答案模\(998244353\)

\(2\le n \le 10^5,0\le g[i]< 998244353\)

我们发现这其实是一个关于\(f\)数组的递推式子,但是肯定不能直接递推

考虑每个对\(f[i]\)有贡献的只有\(f[1]\sim f[i-1]\),我们可以用\(cdq\)分治

假设我们求出了\(f[l->mid]\)的答案,想计算对\(f[mid+1->r]\)的贡献

那么对\(t\in [mid+1,r]\)的贡献为 \(val_t=\sum\limits_{i=l}^{mid}f[i]*g[t-i]\)

是一个卷积形式,可以\(ntt\),得出\(val_t\)后直接加给\(f[t]\)就好了

其实点名是\(cdq\)分治思路就很清晰了吧,不过边界一如既往的恶心我

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
const int N=5e5+10,p=998244353,G=3,gi=332748118;
int n;
int g[N],f[N],pos[N];
int a[N],b[N];
inline int fast(int x,int k)
{
int ret=1;
while(k)
{
if(k&1) ret=ret*x%p;
x=x*x%p;
k>>=1;
}
return ret;
}
inline void ntt(int *a,int inv,int limit)
{
for(int i=0;i<limit;++i)
if(i<pos[i]) swap(a[i],a[pos[i]]);
for(int mid=1;mid<limit;mid<<=1)
{
int Wn=fast(inv?G:gi,(p-1)/(mid<<1));
for(int r=mid<<1,j=0;j<limit;j+=r)
{
int w=1;
for(int k=0;k<mid;++k,w=w*Wn%p)
{
int x=a[j+k],y=w*a[j+k+mid]%p;
a[j+k]=x+y;
if(a[j+k]>=p) a[j+k]-=p;
a[j+k+mid]=x-y;
if(a[j+k+mid]<0) a[j+k+mid]+=p;
}
}
}
if(inv) return;
inv=fast(limit,p-2);
for(int i=0;i<limit;++i) a[i]=a[i]*inv%p;
}
inline void cdq(int l,int r)
{
if(l==r) return;
int mid=(l+r)>>1;
cdq(l,mid);
int limit=1,len=0;
while(limit<=(mid-l+1)*2) limit<<=1,++len;
for(int i=0;i<limit;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(len-1));
for(int i=0;i<limit;++i) a[i]=b[i]=0;
for(int i=l;i<=mid;++i) a[i-l]=f[i];
for(int i=1;i<=r-l+1;++i) b[i-1]=g[i];
ntt(a,1,limit);ntt(b,1,limit);
for(int i=0;i<limit;++i) a[i]=a[i]*b[i]%p;
ntt(a,0,limit);
for(int i=mid+1;i<=r;++i) (f[i]+=a[i-l-1])%=p;
cdq(mid+1,r);
}
inline void main()
{
n=read();
f[0]=1;
for(int i=1;i<n;++i) g[i]=read();
cdq(0,n-1);
for(int i=0;i<n;++i) printf("%lld ",f[i]);
}
}
signed main()
{
red::main();
return 0;
}

最新文章

  1. Linux查看系统运行情况
  2. 微信公共平台开发-(.net实现)5--access_token过期的问题
  3. 横竖屏切换时,Activity的生命周期
  4. php图片转为资源数据
  5. create file遇到操作系统错误5拒绝访问
  6. linux rdsktop 运程管理 windows
  7. ThinkPHP 3.2版本 , 无法读取$_SESSION[&#39;verify_code&#39;]
  8. Android:自定义滚动边缘(EdgeEffect)效果
  9. 技术七Gitservergitolite要构建和操作方便
  10. 有向图的邻接矩阵表示法(创建,DFS,BFS)
  11. onmousedown活用之鼠标拖动
  12. 【 js 模块加载 】深入学习模块化加载(node.js 模块源码)
  13. 还原数据库“XXX”时失败。System.Data.SqlClient.SqlError: 无法执行 BACKUP LOG,因为当前没有数据库备份。
  14. nsq源码阅读笔记之nsqd(二)——Topic
  15. CTF比赛 十一月场 Look 复现
  16. 关于weblogic部署Java项目的包冲突问题
  17. Spark SQL External DataSource简介
  18. 晨读笔记:CSS3选择器之属性选择器
  19. BZOJ1895Pku3580 supermemo——非旋转treap
  20. Qt sprintf_s函数格式化字符串出错

热门文章

  1. swift声明属性为某个类型同时遵循某协议
  2. 20190312_浅谈go&amp;java差异(二)
  3. [20191126]探究等待事件的本源2.txt
  4. [PHP] RBAC权限与审批流的简单数据库构想
  5. Appium(四):真实机第一个appium程序、模拟器第一个appium程序、查看元素
  6. pytest系列(一):什么是单元测试界的高富帅?
  7. docker工具之基本命令
  8. pycharm添加快捷键:
  9. vue介绍以及相关概念理解大全
  10. linux查看占用端口号的程序及pid