Contest Hunter 弱省胡策#5 Handle NTT
2015-09-11 19:20
330 查看
题意:链接
方法: NTT
解析:
Bi=∑nj=iCij∗Aj(modBi=\sum_{j=i}^{n}C_{j}^{i}*A_j(mod 998244353)998244353)
首先它给出来的这个数的原根是3……..
然后我们要转化这个式子,把C打开。
变成了Bi∗i!=∑nj=ij!∗Aj(j−i)!B_i*i!=\sum_{j=i}^{n}\frac{j!*A_j}{(j-i)!}
设Cn−i=Bi∗i!C_{n-i}=B_i*i!,Dj=An−j=Aj∗j!D_j=A_{n-j}=A_j*j!
所以原方程转化为
Ci=∑ij=0Dj∗1(i−j)!C_i=\sum_{j=0}^{i}D_j*\frac{1}{(i-j)!}
我看到了啥?卷积!卷积!
PoPoQQQ
是的!就这么神奇的变成了卷积!卷积!
设F(x)=∑ni=0Ci∗xiF(x)=\sum_{i=0}^{n}C_i*x^i
设G(x)=∑ni=0Di∗xiG(x)=\sum_{i=0}^{n}D_i*x^i
设H(x)=∑ni=01i!∗xiH(x)=\sum_{i=0}^{n}\frac{1}{i!}*x^i
于是F(x)=G(x)*H(x)。
但是注意,我们知道的是F(x)以及H(x),这怎么求G(x)呢?
其实转化一下就好了。
G(x)=F(x)∗H−1(x)G(x)=F(x)*H^{-1}(x)
H(x)=10!+11!+12!+...+1n!=exH(x)=\frac{1}{0!}+\frac{1}{1!}+\frac{1}{2!}+...+\frac{1}{n!}=e^x
所以H−1(x)=e−x=10!−11!+12!−13!.....H^{-1}(x)=e^{-x}=\frac{1}{0!}-\frac{1}{1!}+\frac{1}{2!}-\frac{1}{3!}.....
于是直接上NTT。
注意前面说的,这个质数的原根是3.
代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 262145 #define mod 998244353 using namespace std; typedef long long ll; int n; ll B ,C ,D ,G ,H ; ll Factor ,Inv_Factor ; int rev ; ll Quick_Power(ll x,ll y,ll MOD) { ll ret=1; while(y) { if(y&1)ret=(ret*x)%MOD; x=(x*x)%MOD; y>>=1; } return ret; } void Init() { Factor[0]=1,Inv_Factor[0]=1; for(int i=1;i<=n;i++) { Factor[i]=Factor[i-1]*i%mod; Inv_Factor[i]=Quick_Power(Factor[i],mod-2,mod); } } void NTT(ll *a,int f) { for(int i=0;i<n;i++)if(i<rev[i])swap(a[i],a[rev[i]]); for(int h=2;h<=n;h<<=1) { ll wn=Quick_Power(3,(mod-1)/h,mod); for(int i=0;i<n;i+=h) { ll w=1; for(int j=0;j<(h>>1);j++,w=w*wn%mod) { ll t=w*a[i+j+(h>>1)]%mod; a[i+j+(h>>1)]=((a[i+j]-t)%mod+mod)%mod; a[i+j]=(a[i+j]+t)%mod; } } } if(f==-1) { for(int i=1;i<(n>>1);i++)swap(a[i],a[n-i]); ll inv=Quick_Power(n,mod-2,mod); for(int i=0;i<n;i++)a[i]=a[i]*inv%mod; } } int main() { scanf("%d",&n); Init(); for(int i=0;i<=n;i++)scanf("%lld",&B[i]); for(int i=0;i<=n;i++)D[n-i]=B[i]*Factor[i]%mod; for(int i=0;i<=n;i++) { if(i&1) G[i]=((-Inv_Factor[i])%mod+mod)%mod; else G[i]=Inv_Factor[i]; } int m=2*n,L=0,nn=n; for(n=1;n<=m;n<<=1)L++; for(int i=0;i<n;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1)); NTT(D,1),NTT(G,1); for(int i=0;i<n;i++)H[i]=D[i]*G[i]%mod; NTT(H,-1); for(int i=0;i<=nn;i++) printf("%lld ",H[nn-i]*Inv_Factor[i]%mod); puts(""); }
相关文章推荐
- dp related problems (update continuously)
- Nodejs课堂笔记-第五课 在nodejs中使用DynamoDB Local
- ajax请求数据,返回数据顺序问题
- iOS开发之 window , UIView
- CentOS配置网易源
- 从零开始自学Swift(六)
- VFL语法-基础
- log4j的使用方法
- 批处理自身%0的总结
- ftp工作原理
- 数塔 2084 (简单的动态规划)
- printf函数详解
- CUDA基础
- 操作系统面试题
- .dll,.lib,.def 和 .exp文件
- Android基础 学习之Dialog
- 循环buffer使数据更安全 效率高
- 从博客中抽取代码——shaidaima.com 原始数据来源
- Java Executor的类关系
- LVS 持久连接 PPC模式、PCC模式、防火墙标记