[第二类斯特林数 组合 分治FFT||多项式求逆] BZOJ 4555 [Tjoi2016&Heoi2016]求和

来源:互联网 发布:c语言简单计算器程序 编辑:程序博客网 时间:2024/05/23 01:12

自己好弱 多项式求逆不会啊

分治FFT也是第一次打




#include<cstdio>#include<cstdlib>#include<algorithm>using namespace std;typedef long long ll;inline ll Pow(ll a,ll b,ll p){  ll ret=1;  for (;b;(a*=a)%=p,b>>=1)  if (b&1)  (ret*=a)%=p;  return ret;  }const int N=300005;const ll P=998244353LL;const ll G=3;//ll G;  inline ll Inv(ll x){  return Pow(x,P-2,P);  }ll inv[N],fac[N];inline void Pre(){fac[0]=1;for (int i=1;i<=300000;i++)fac[i]=fac[i-1]*i%P;inv[1]=1;for (int i=2;i<=300000;i++)inv[i]=(P-P/i)*inv[P%i]%P;inv[0]=1;for (int i=1;i<=300000;i++)(inv[i]*=inv[i-1])%=P;}ll f[100005];  inline ll GetRoot(ll p,ll phi)  {  int c=0;  for (int i=2;i*i<=phi;i++) if (phi%i==0) f[++c]=i,f[++c]=phi/i;  for (int g=2;g<p;g++){  int j;for (j=1;j<=c;j++) if (Pow(g,f[j],p)==1) break;  if (j==c+1) return g;  }return 0;}ll n,nn;ll L,w[2][N],R[N];inline void Init(int m){//G=GetRoot(P,P-1);  L=0; for (n=1;n<=(m<<1);n<<=1) L++;  for (int i=0;i<n;i++) R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));  w[0][0]=w[0][n]=1;  ll t=Pow(G,(P-1)/n,P);  for (int i=1;i<n;i++) w[0][i]=w[0][i-1]*t%P;  for (int i=0;i<=n;i++) w[1][i]=w[0][n-i];}inline void NTT(ll *a,int r){for (int i=0;i<n;i++) if (i<R[i]) swap(a[i],a[R[i]]);for (int i=1;i<n;i<<=1)for (int j=0;j<n;j+=(i<<1))for (int k=0;k<i;k++){ll x=a[j+k],y=w[r][n/(i<<1)*k]*a[j+k+i]%P;a[j+k]=(x+y)%P; a[j+k+i]=(x-y+P)%P;}   if (r==1) for (int i=0,inv=Inv(n);i<n;i++) a[i]=a[i]*inv%P;  }ll g[N<<1];ll A[N<<1],B[N<<1];inline void Solve(int l,int r){if (l==r) return;int mid=((l+r)>>1),m=r-l;Solve(l,mid);Init(m-1);for (int i=0;i<n;i++) A[i]=B[i]=0;for (int i=l;i<=mid;i++) A[i-l]=g[i];for (int i=l+1;i<=r;i++) B[i-l-1]=2LL*inv[i-l]%P;NTT(A,0); NTT(B,0);for (int i=0;i<n;i++) A[i]=A[i]*B[i]%P;NTT(A,1);for (int i=mid+1;i<=r;i++)(g[i]+=A[i-l-1])%=P;Solve(mid+1,r);}int main(){freopen("t.in","r",stdin);freopen("t.out","w",stdout);scanf("%lld",&nn);Pre();for (n=1;n<=nn;n<<=1);  g[0]=1; Solve(0,n-1);ll ans=0;for (int i=0;i<=nn;i++)(ans+=g[i]*fac[i]%P)%=P;printf("%lld\n",ans);return 0;}


0 0