题意:链接
方法: NTT
解析:
Bi=∑nj=iCij?Aj(mod
998244353)
首先它给出来的这个数的原根是3……..
然后我们要转化这个式子,把C打开。
变成了
Bi?i!=∑nj=ij!?Aj(j?i)!
设
Cn?i=Bi?i!
,
Dj=An?j=Aj?j!
所以原方程转化为
Ci=∑ij=0Dj?1(i?j)!
我看到了啥?卷积!卷积!
PoPoQQQ
是的!就这么神奇的变成了卷积!卷积!
设
F(x)=∑ni=0Ci?xi
设
G(x)=∑ni=0Di?xi
设
H(x)=∑ni=01i!?xi
于是F(x)=G(x)*H(x)。
但是注意,我们知道的是F(x)以及H(x),这怎么求G(x)呢?
其实转化一下就好了。
G(x)=F(x)?H?1(x)
H(x)=10!+11!+12!+...+1n!=ex
所以
H?1(x)=e?x=10!?11!+12!?13!.....
于是直接上NTT。
注意前面说的,这个质数的原根是3.
代码:
using namespace std;
typedef long long ll;
int n;
ll B[N],C[N],D[N],G[N],H[N];
ll Factor[N],Inv_Factor[N];
int rev[N];
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);
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("");
}