记录编号 488624 评测结果 AATTTTTTTT
题目名称 [HZOI 2015] 有标号的DAG计数 II 最终得分 20
用户昵称 Gravatar支羽 是否通过 未通过
代码语言 C++ 运行时间 8.695 s
提交时间 2018-02-22 19:52:59 内存使用 7.43 MiB
显示代码纯文本
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#define LL long long
#define FILE "dag_count"
//#define FILE "分治"
#define Mod (998244353)
#define G (3)
#define sq2 (116195171)
#define rg register
using namespace std;

const int N = 300010;
int fac[N],facInv[N],Pow[N],Inv[N];
int rev[N],a[N],b[N],f[N],gn[N];

inline int gi(){
  int x=0,res=1;char ch=getchar();
  while(ch>'9' || ch<'0')res^=ch=='-',ch=getchar();
  while(ch>='0'&&ch<='9')x=x*10+ch-48,ch=getchar();
  return res?x:-x;
}

inline int QPow(int d,int z,int ans=1){
  for(;z;z>>=1,d=1ll*d*d%Mod)
    if(z&1)ans=1ll*ans*d%Mod;
  return ans;
}

inline void prepare(int n){
  for(int i=1;i<=n+n+2;i<<=1)
    gn[i]=QPow(G,(Mod-1)/(i<<1));
  fac[0]=Pow[0]=1;
  for(int i=1;i<=n;++i)
    fac[i]=1ll*fac[i-1]*i%Mod;
  facInv[n]=QPow(fac[n],Mod-2);
  for(int i=n-1;i>=0;--i)
    facInv[i]=1ll*facInv[i+1]*(i+1)%Mod;
  for(int i=0;i<=n;++i){
    Pow[i]=QPow(sq2,1ll*i*i%(Mod-1));
    Inv[i]=QPow(Pow[i],Mod-2);
  }
}

inline void NTT(int *A,int n,int f){
  for(int i=1;i<n;++i)
    if(i<rev[i])swap(A[i],A[rev[i]]);
  for(int i=1;i<n;i<<=1){
    for(int j=0;j<n;j+=(i<<1)){
      rg int g=1,x,y;
      for(int k=0;k<i;++k,g=1ll*g*gn[i]%Mod){
        x=A[j+k];y=1ll*g*A[i+j+k]%Mod;
        A[j+k]=(x+y)%Mod;A[i+j+k]=(x-y)%Mod;
      }
    }
  }
  if(f==1)return;reverse(A+1,A+n);
  int iv=QPow(n,Mod-2);
  for(int i=0;i<n;++i)A[i]=1ll*A[i]*iv%Mod;
}

inline void solve(int l,int r){
  if(l==r){f[l]=(f[l]%Mod+Mod)%Mod;return;}
  int mid=(l+r)>>1,n=1,L=0;
  solve(l,mid);
  for(;n<=r+mid-l-l;n<<=1)L++;
  for(int i=0;i<n;++i)
    rev[i]=(rev[i/2]/2)|((i&1)<<(L-1));
  for(int i=l;i<=mid;++i)a[i-l]=f[i];
  for(int i=1,j=1;i<=r-l;++i,j=-j)
    b[i]=1ll*j*facInv[i]*Inv[i]%Mod;
  NTT(a,n,1);NTT(b,n,1);
  for(int i=0;i<n;++i)a[i]=1ll*a[i]*b[i]%Mod;
  NTT(a,n,-1);
  for(int i=mid+1;i<=r;++i)f[i]=(f[i]+a[i-l])%Mod;
  for(int i=0;i<n;++i)a[i]=b[i]=0;
  solve(mid+1,r);
}

int main(){
  freopen(FILE".in","r",stdin);
  freopen(FILE".out","w",stdout);
  int n=gi();prepare(n);f[0]=1;
  solve(0,n);f[n]=(f[n]+Mod)%Mod;
  f[n]=1ll*f[n]*fac[n]%Mod*Pow[n]%Mod;
  printf("%d\n",f[n]);  
  fclose(stdin);fclose(stdout);
  return 0;
}