[数学记录]51nod1514 美妙的序列
command_block · · 个人记录
题意 : 对于一个长度为
给出
移项可得
当
设
则有
多项式求逆即可。
#include<algorithm>
#include<cstring>
#include<cstdio>
#define ll long long
#define ull unsigned long long
#define clr(f,n) memset(f,0,sizeof(int)*(n))
#define cpy(f,g,n) memcpy(f,g,sizeof(int)*(n))
using namespace std;
const int _G=3,mod=998244353,Maxn=135000;
ll powM(ll a,int t=mod-2){
ll ans=1;
while(t){
if(t&1)ans=ans*a%mod;
a=a*a%mod;t>>=1;
}return ans;
}
const int invG=powM(_G);
int tr[Maxn<<1],tf;
void tpre(int n){
if (tf==n)return ;tf=n;
for(int i=0;i<n;i++)
tr[i]=(tr[i>>1]>>1)|((i&1)?n>>1:0);
}
void NTT(int *g,bool op,int n)
{
tpre(n);
static ull f[Maxn<<1],w[Maxn<<1]={1};
for (int i=0;i<n;i++)f[i]=(((ll)mod<<5)+g[tr[i]])%mod;
for(int l=1;l<n;l<<=1){
ull tG=powM(op?_G:invG,(mod-1)/(l+l));
for (int i=1;i<l;i++)w[i]=w[i-1]*tG%mod;
for(int k=0;k<n;k+=l+l)
for(int p=0;p<l;p++){
int tt=w[p]*f[k|l|p]%mod;
f[k|l|p]=f[k|p]+mod-tt;
f[k|p]+=tt;
}
if (l==(1<<10))
for (int i=0;i<n;i++)f[i]%=mod;
}if (!op){
ull invn=powM(n);
for(int i=0;i<n;++i)
g[i]=f[i]%mod*invn%mod;
}else for(int i=0;i<n;++i)g[i]=f[i]%mod;
}
void px(int *f,int *g,int n)
{for(int i=0;i<n;++i)f[i]=1ll*f[i]*g[i]%mod;}
int _g1[Maxn<<1];
#define sav _g1
void times(int *f,int *g,int len,int lim)
{
int n=1;for(n;n<len+len;n<<=1);
cpy(sav,g,n);
for(int i=len;i<n;i++)sav[i]=0;
NTT(f,1,n);NTT(sav,1,n);
px(f,sav,n);NTT(f,0,n);
for(int i=lim;i<n;++i)f[i]=0;
clr(sav,n);
}
void invp(int *f,int m)
{
static int w[Maxn<<1],r[Maxn<<1];
int n;for (n=1;n<m;n<<=1);
w[0]=powM(f[0]);
for (int len=2;len<=n;len<<=1){
for (int i=0;i<(len>>1);i++)
r[i]=(w[i]<<1)%mod;
cpy(sav,f,len);
NTT(w,1,len<<1);px(w,w,len<<1);
NTT(sav,1,len<<1);px(w,sav,len<<1);
NTT(w,0,len<<1);clr(w+len,len);
for (int i=0;i<len;i++)
w[i]=(r[i]-w[i]+mod)%mod;
}cpy(f,w,m);clr(sav,n+n);clr(w,n+n);clr(r,n+n);
}
int T,n,m[Maxn],F[Maxn];
int main()
{
scanf("%d",&T);
for (int i=1;i<=T;i++){
scanf("%d",&m[i]);
n=max(n,m[i]);
}
n++;F[0]=1;
for (int i=1;i<=n;i++)
F[i]=1ll*F[i-1]*i%mod;
invp(F,n);
for (int i=0;i<n;i++)
F[i]=mod+(i==0)-F[i];
for (int i=1;i<=T;i++)
printf("%d\n",F[m[i]]);
return 0;
}