bzoj 3456 城市规划 - 多项式理论

就是直接EGF求ln即可。
EGF参见这篇博客

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define N 1600010
#define p 1004535809
#define clr(a,n) memset(a,0,sizeof(int)*(n))
#define cpy(a,b,n) memcpy(a,b,sizeof(int)*(n))
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
inline int fast_pow(int x,lint k,int ans=1)
{   for(;k;k>>=1,x=(lint)x*x%p) (k&1)?ans=(lint)ans*x%p:0;return ans; }
int h[N],f[N];
namespace NTT_space{
    int h[N],t[N],r[N],A1[N],A2[N];
    inline int NTT(int *a,int n,int s)
    {
        for(int i=1;i<n;i++) if(i<r[i]) swap(a[i],a[r[i]]);
        for(int i=2;i<=n;i<<=1)
        {
            int wn=fast_pow(3,(s>0)?(p-1)/i:p-1-(p-1)/i);
            for(int j=0,t=i>>1;j<n;j+=i)
                for(int k=0,w=1;k<t;k++,w=(lint)w*wn%p)
                {
                    int x=a[j+k],y=(lint)w*a[j+k+t]%p;
                    a[j+k]=(x+y)%p,a[j+k+t]=(x-y+p)%p;
                }
        }
        int ninv=fast_pow(n,p-2);
        if(s<0) rep(i,0,n-1) a[i]=(lint)a[i]*ninv%p;
        return 0;
    }
    inline int tms(int *a,int *b,int *c,int n,int m)//c=ab,a[n]=b[m]=0
    {
        int k=1,L=0;while(k<n+m) k<<=1,L++;
        rep(i,1,k-1) r[i]=(r[i>>1]>>1)|((i&1)<<(L-1));
        clr(A1,k),cpy(A1,a,n),NTT(A1,k,1),
        clr(A2,k),cpy(A2,b,m),NTT(A2,k,1);
        rep(i,0,k-1) c[i]=(lint)A1[i]*A2[i]%p;
        return NTT(c,k,-1);
    }
    inline int tms(int *a,int *b,int *c,int n) { return tms(a,b,c,n,n); }
    inline int polyinv(int *a,int *inv,int m)
    {
        int n=1;while(n<=m) n<<=1;
        clr(inv,n),inv[0]=fast_pow(a[0],p-2);
        for(int i=2;i<=n;i<<=1)
        {
            cpy(h,inv,i);rep(j,0,i-1) h[j]=2ll*h[j],(h[j]>=p?h[j]-=p:0);
            tms(inv,inv,inv,i>>1),tms(inv,a,inv,i);
            rep(j,0,i-1) inv[j]=h[j]-inv[j],(inv[j]<0?inv[j]+=p:0);
            clr(inv+i,i);
        }
        return 0;
    }
    inline int polydif(int *a,int *b,int n)
    {
        b[n]=0;rep(i,0,n-1) b[i]=(i+1ll)*a[i+1]%p;return 0;
    }
    inline int polyint(int *a,int *b,int n)
    {
        b[0]=0;rep(i,1,n) b[i]=(lint)a[i-1]*fast_pow(i,p-2)%p;return 0;
    }
    inline int polyln(int *a,int *pln,int n)
    {
        return polyinv(a,pln,n),polydif(a,h,n),tms(pln,h,h,n),polyint(h,pln,n);
    }
    inline int polyexp(int *a,int *e,int m)
    {
        int n=1;while(n<=m*2) n<<=1;
        clr(e,n),e[0]=1;
        for(int i=2;i<=n;i<<=1)
        {
            polyln(e,t,i>>1);
            for(int j=0;j<(i>>1);j++) t[j]=(a[j]-t[j]+(j==0)+p)%p;
            tms(e,t,e,i>>1),clr(e+i,i);
        }
        return 0;
    }
}
using NTT_space::tms;
using NTT_space::polyinv;
using NTT_space::polyln;
using NTT_space::polydif;
using NTT_space::polyint;
using NTT_space::polyexp;
int fac[N],facinv[N];
inline int prelude(int n)
{
    rep(i,fac[0]=1,n) fac[i]=(lint)fac[i-1]*i%p;
    facinv[n]=fast_pow(fac[n],p-2);
    for(int i=n-1;i>=0;i--)
        facinv[i]=(i+1ll)*facinv[i+1]%p;
    return 0;
}
int main()
{
    int n=inn();prelude(n+1);
    rep(i,0,n+1) h[i]=(lint)fast_pow(2,i*(i-1ll)/2)*facinv[i]%p;
    return polyln(h,f,n+1),!printf("%d\n",int((lint)f[n]*fac[n]%p));
}


猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/83961351
今日推荐