看来我得恶补组合数学了...
先回忆一下指数生成函数乘积的性质:若$\begin{align*}A_e(x)=\sum\limits_{n=0}^\infty a_n\dfrac{x^n}{n!},B_e(x)=\sum\limits_{n=0}^\infty b_n\dfrac{x^n}{n!}\end{align*}$,那么$\begin{align*}A_e(x)B_e(x)=\sum\limits_{n=0}^\infty c_n\dfrac{x^n}{n!}\end{align*}$,其中$\begin{align*}c_n=\sum\limits_{k=0}^n\binom nka_kb_{n-k}\end{align*}$,相当于普通卷积前面多一个组合数的系数
回到本题,设答案为$f_n$,它的指数生成函数为$F(x)$,那么$n![x^n]\dfrac{F^m(x)}{m!}$计数了$n$个带标号点的图被分成$m$个连通块的方案数(先带标号地取$m$组点,把它们分别连成连通块,最后消序,在外面乘一个阶乘是为了抵消指数生成函数的阶乘)
对$m$求和,我们就得到了所有不同的图的数量,这个可以直接算:$2^\binom n2$(两两选点,连/不连边),设它的指数生成函数为$G(x)$
于是我们有$\begin{align*}G(x)=\sum\limits_{m=0}^\infty\dfrac{F^m(x)}{m!}=e^{F(x)}\end{align*}$(从$0$开始求和是因为$G(x)$的常数项为$1$,而$\dfrac{F^0(x)}{0!}$刚好也是$1$),也就是$F(x)=\ln G(x)$
多项式求自然对数:给定$G(x)$,求$F(x)=\ln G(x)$
$\begin{align*}F(x)&=\ln G(x)\\F'(x)&=\dfrac{G'(x)}{G(x)}\\F(x)&=\int\dfrac{G'(x)}{G(x)}dx\end{align*}$
所以直接多项式求逆,微分和积分都是$O(n)$的,总时间复杂度$O(n\log_2n)$
#include<stdio.h>
#include<string.h>
const int mod=1004535809;
typedef long long ll;
int mul(int a,int b){return a*(ll)b%mod;}
int ad(int a,int b){return(a+b)%mod;}
int de(int a,int b){return(a-b)%mod;}
int rev[300010],N,iN;
int pow(int a,ll b){
int s=1;
while(b){
if(b&1)s=mul(s,a);
a=mul(a,a);
b>>=1;
}
return s;
}
void pre(int n){
int i,k;
for(N=1,k=0;N<n;N<<=1)k++;
for(i=0;i<N;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
iN=pow(N,mod-2);
}
void swap(int&a,int&b){a^=b^=a^=b;}
void ntt(int*a,int on){
int i,j,k,t,w,wn;
for(i=0;i<N;i++){
if(i<rev[i])swap(a[i],a[rev[i]]);
}
for(i=2;i<=N;i<<=1){
wn=pow(3,(on==1)?(mod-1)/i:(mod-1-(mod-1)/i));
for(j=0;j<N;j+=i){
w=1;
for(k=0;k<i>>1;k++){
t=mul(w,a[i/2+j+k]);
a[i/2+j+k]=de(a[j+k],t);
a[j+k]=ad(a[j+k],t);
w=mul(w,wn);
}
}
}
if(on==-1){
for(i=0;i<N;i++)a[i]=mul(a[i],iN);
}
}
int t0[300010];
void getinv(int*a,int*b,int n){
if(n==1){
b[0]=pow(a[0],mod-2);
return;
}
int i;
getinv(a,b,n>>1);
pre(n<<1);
memset(t0,0,sizeof(t0));
for(i=0;i<n;i++)t0[i]=a[i];
ntt(t0,1);
ntt(b,1);
for(i=0;i<N;i++)b[i]=mul(b[i],de(2,mul(b[i],t0[i])));
ntt(b,-1);
for(i=n;i<N;i++)b[i]=0;
}
int t1[300010],t2[300010],inv[300010];
void getln(int*a,int n){
int i;
getinv(a,t1,n);
for(i=1;i<n;i++)t2[i-1]=mul(i,a[i]);
ntt(t1,1);
ntt(t2,1);
for(i=0;i<N;i++)a[i]=mul(t1[i],t2[i]);
ntt(a,-1);
for(i=n-1;i>0;i--)a[i]=mul(a[i-1],inv[i]);
a[0]=0;
for(i=n;i<N;i++)a[i]=0;
}
#define N 300000
int fac[300010],rfac[300010],a[300010];
int main(){
int n,i;
scanf("%d",&n);
fac[0]=1;
for(i=1;i<=N;i++)fac[i]=mul(fac[i-1],i);
rfac[N]=pow(fac[N],mod-2);
for(i=N;i>0;i--)rfac[i-1]=mul(rfac[i],i);
for(i=1;i<=N;i++)inv[i]=mul(rfac[i],fac[i-1]);
for(i=0;i<=n;i++)a[i]=mul(pow(2,i*(ll)(i-1)/2),rfac[i]);
for(i=1;i<n+1;i<<=1);
getln(a,i);
printf("%d",(mul(a[n],fac[n])+mod)%mod);
}