description

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

\[f[i]=\sum_{j=1}^if[i-j]g[j]
\]

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


analysis

  • 一道分治\(NTT\)板题

  • 经历过城市规划那题的洗礼之后这题变得微不足道

  • 考虑\(CDQ\)分治,求出\([l,mid]\)对\([mid+r]\)的贡献

  • 把\(f[l,mid]\)拉出来,与\(g[1..r-l]\)相乘,答案数组的后\(r-mid\)位就是分别对\([mid+r]\)的贡献

  • 具体可以画出两个多项式在分治过程中的相乘,结合每一个\(f\)的值就可以弄清楚

  • 由于这个\(NTT\)很清真所以\(l==r\)时就直接\(return\)了,当然也没有各种阶乘逆元什么的

  • 下次学多项式求逆再来做一次这题 (FLAG)


code

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 400005
#define G 3
#define mod 998244353
#define ll long long
#define reg register ll
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i) using namespace std; ll f[MAXN],g[MAXN];
ll a[MAXN],b[MAXN],rev[MAXN];
ll n,m; inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
inline ll work(ll x)
{
ll y=1;
while (y<x)y<<=1;
return y<<1;
}
inline ll pow(ll x,ll y)
{
ll z=1;
while (y)
{
if (y&1)z=z*x%mod;
x=x*x%mod,y>>=1;
}
return z;
}
inline void ntt(ll a[],ll len,ll inv)
{
ll bit=0;
while ((1<<bit)<len)++bit;
fo(i,0,len-1)
{
rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
if (i<rev[i])swap(a[i],a[rev[i]]);
}
for (ll mid=1;mid<len;mid*=2)
{
ll tmp=pow(G,(mod-1)/(mid*2));
if (inv==-1)tmp=pow(tmp,mod-2);
for (ll i=0;i<len;i+=mid*2)
{
ll omega=1;
for (ll j=0;j<mid;++j,omega=omega*tmp%mod)
{
ll x=a[i+j],y=omega*a[i+j+mid]%mod;
a[i+j]=(x+y)%mod,a[i+j+mid]=(x-y+mod)%mod;
}
}
}
}
inline void CDQ(ll l,ll r)
{
if (l==r)return;
ll mid=(l+r)>>1;
CDQ(l,mid);
ll len=work(r-l+1),invv=pow(len,mod-2);
fo(i,0,len-1)a[i]=b[i]=0;
fo(i,1,mid-l+1)a[i]=f[l+i-1];
fo(i,1,r-l)b[i]=g[i];
ntt(a,len,1),ntt(b,len,1);
fo(i,0,len-1)a[i]=(a[i]*b[i]%mod);
ntt(a,len,-1);
fo(i,0,len-1)a[i]=(a[i]*invv)%mod;
fo(i,mid+1,r)(f[i]+=a[i-l+1])%=mod;
CDQ(mid+1,r);
}
int main()
{
freopen("CDQNTT.in","r",stdin);
n=read(),m=work(n);
fo(i,1,n-1)g[i]=read();
f[1]=1,CDQ(1,m/2);
fo(i,1,n)printf("%lld ",f[i]);
printf("\n");
return 0;
}

最新文章

  1. Mono 3.8发布:性能进一步改进,可伸缩性提升
  2. 垂直居中display:table;
  3. 症状解决,原因不详的用非默认管理权限账户登录COM注册成功但找不到类型问题
  4. 在Ubuntu中安装Python3
  5. GJM : 用JIRA管理你的项目(一)JIRA环境搭建 [转载]
  6. KMeans的图像压缩
  7. Linux 守护进程一
  8. 【MPI学习5】MPI并行程序设计模式:组通信MPI程序设计
  9. sql server 2012序列号
  10. hdu3308LCIS(线段树,点更新,段查寻,查寻时一定要注意跨越时如何计算)
  11. python特征提取——pyAudioAnalysis工具包
  12. Mac OS X 10.10优胜美地如何完美接管iphone上的电话和短信
  13. Microsoft SQL - 学习总目录
  14. centos关闭邮件提醒
  15. SSO单点登录_理解
  16. centos7编译安装zabbix(附带编译安装lnmp)
  17. VC中function函数解析
  18. JavaSE-java8-谓词复合的用法
  19. rsync 实现文件同步 (重要数据通过rsyncr把数据同步到不同的两台服务器上,这样可以防止服务器的硬盘故障导致数据丢失) 客户端同步时如果要排某个目录
  20. 手把手教你学node.js 之使用 eventproxy 控制并发

热门文章

  1. 第五篇 scrapy安装及目录结构,启动spider项目
  2. md详解和rd详解:一次性创建多个目录和多级子目录
  3. linux部署tomcat项目
  4. html input 上capture 参数在 安卓 苹果上的异同
  5. No identifier specified for entity: com.XXX.XXX...
  6. leetcode-158周赛-5222-分割字符串
  7. [原创] delphi Memo 滚动到底部/开始 [Delphi XE、Delphi 7]
  8. Android中的广播Broadcast详解
  9. 下面是一段delphi代码,你在c# 中引入api 即可
  10. Notepad++如何对比文件 Notepad++对比两个文件代码方法