【BZOJ3456】轩辕朗的城市规划 EGF+多项式求ln

我们构造$f(i)$和$g(i)$。

其中$f(x)$表示由$x$个节点构成的无向简单连通图的个数。

$g(x)$表示有$x$个节点构成的无向简单图(不要求连通)的个数。

显然,由$x$个节点构成的无向简单图最多能有$\binom{x}{2}$条边,那么$g(x)=2^{\binom{x}{2}}$。

然后我们构造$f(x)$和$g(x)$的$EGF$:

$F(x)=\sum_{i=0}^{\infty} f(i) \times \frac{x^i}{i!}$。

$G(x)=\sum_{i=0}^{\infty} g(i) \times \frac{x^i}{i!}\ =\sum_{i=0}^{\infty} 2^{\binom{x}{2}} \times \frac{x^i}{i!}$。

然后我们又不难发现,$G(x)=\sum_{i=0}^{\infty} \frac{F(x)^i}{i!}$。(这个式子可以这样理解:图中包含$1$个联通块的生成函数为$F(x)$,包含$2$个连通块的生成函数为$\frac{1}{2}F^2(x)$,包含$3$个连通块的生成函数为$\frac{1}{3!} F^3(x)$,以此类推)

考虑到$e^x$的泰勒展开式为$\sum_{i=0}^{\infty} \frac{x^i}{i!}$,则 $G(x)=e^{F(x)}$。

由于多项式$G(x)$我们已经求得,则$F(x)=ln(G(x))$。

则答案为$[x^n]F(n) \times n!$。

考虑到多项式求ln的时间复杂度为O(n long n),则该算法的时间复杂度为O(n log n)。

 

 1 #include<bits/stdc++.h>
 2 #define M (1<<19)
 3 #define L long long
 4 #define G 3
 5 #define MOD 1004535809
 6 using namespace std;
 7 
 8 L pow_mod(L x,L k){
 9     L ans=1;
10     while(k){
11         if(k&1) ans=ans*x%MOD;
12         x=x*x%MOD; k>>=1;
13     }
14     return ans;
15 }
16 
17 void change(L a[],int n){
18     for(int i=0,j=0;i<n-1;i++){
19         if(i<j) swap(a[i],a[j]);
20         int k=n>>1;
21         while(j>=k) j-=k,k>>=1;
22         j+=k;
23     }
24 }
25 void NTT(L a[],int n,int on){
26     change(a,n);
27     for(int h=2;h<=n;h<<=1){
28         L wn=pow_mod(G,(MOD-1)/h);
29         for(int j=0;j<n;j+=h){
30             L w=1;
31             for(int k=j;k<j+(h>>1);k++){
32                 L u=a[k],t=a[k+(h>>1)]*w%MOD;
33                 a[k]=(u+t)%MOD;
34                 a[k+(h>>1)]=(u-t+MOD)%MOD;
35                 w=w*wn%MOD;
36             }
37         }
38     }
39     if(on==-1){
40         L inv=pow_mod(n,MOD-2);
41         for(int i=0;i<n;i++) a[i]=a[i]*inv%MOD;
42         reverse(a+1,a+n);
43     }
44 }
45 
46 void getinv(L a[],L b[],int n){
47     if(n==1){b[0]=pow_mod(a[0],MOD-2); return;}
48     static L c[M],d[M];
49     memset(c,0,M<<3); memset(d,0,M<<3);
50     getinv(a,c,n>>1);
51     for(int i=0;i<n;i++) d[i]=a[i];
52     NTT(d,n<<1,1); NTT(c,n<<1,1);
53     for(int i=0;i<(n<<1);i++) b[i]=(2*c[i]-d[i]*c[i]%MOD*c[i]%MOD+MOD)%MOD;
54     NTT(b,n<<1,-1);
55     for(int i=0;i<n;i++) b[i+n]=0;
56 }
57 
58 void qiudao(L a[],L b[],int n){
59     for(int i=1;i<n;i++) b[i-1]=a[i]*i%MOD;
60 }
61 void jifen(L a[],L b[],int n){
62     for(int i=0;i<n;i++) b[i+1]=a[i]*pow_mod(i+1,MOD-2)%MOD;
63 }
64 
65 void getln(L a[],L b[],int n){
66     static L inva[M],pia[M];
67     memset(inva,0,M<<3); memset(pia,0,M<<3);
68     getinv(a,pia,n); qiudao(a,inva,n); 
69     NTT(pia,n<<1,1); NTT(inva,n<<1,1);
70     for(int i=0;i<(n<<1);i++) pia[i]=pia[i]*inva[i]%MOD;
71     NTT(pia,n<<1,-1);
72     jifen(pia,b,n);
73 }
74 
75 L a[M]={0},f[M]={0};
76 L fac[M]={0},invfac[M]={0};
77 
78 int main(){
79     fac[0]=1;
80     int n; scanf("%d",&n);
81     int nn=1; while(nn<=n) nn<<=1;
82 
83     for(int i=1;i<nn;i++) fac[i]=fac[i-1]*i%MOD;
84     invfac[nn-1]=pow_mod(fac[nn-1],MOD-2);
85     for(int i=nn-2;~i;i--) invfac[i]=invfac[i+1]*(i+1)%MOD;
86 
87     for(L i=0;i<nn;i++) a[i]=pow_mod(2,i*(i-1)/2)*invfac[i]%MOD;
88     getln(a,f,nn);
89     
90     printf("%lld\n",f[n]*fac[n]%MOD);
91 }

 

posted @ 2018-05-22 14:09  AlphaInf  阅读(289)  评论(0编辑  收藏  举报