题意:让你求n个点所构成的无向连通图的方案数,n<=130000
解析:我么考虑一下推式子
设f[i]为i个点所构成的无向连通图的个数
g[i]为i个点所构成的无向图的个数
我们发现
然后还是展开组合数
然后我们把他们看做
然后我们可以直接多项式求拟了
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN=6e5+10;
const int N=2e5;
const ll mod=1004535809;
ll n,a[MAXN],b[MAXN],g[MAXN],f[MAXN],fac[MAXN],inv[MAXN];
int len,k;
int rev[MAXN];
ll ksm(ll x,ll y)
{
ll ans=1;
for (;y;y>>=1,x=(x*x)%mod) if (y&1) ans=(ans*x)%mod;
return ans;
}
void init()
{
fac[0]=1;
for (int i=1;i<=N;i++) fac[i]=(fac[i-1]*(ll)i)%mod;
inv[0]=inv[1]=1;
for (int i=2;i<=N;i++) inv[i]=((mod-mod/i)*inv[mod%i])%mod;
for (int i=2;i<=N;i++) inv[i]=(inv[i-1]*inv[i])%mod;
}
void NTT(ll *a,int len,int t)
{
for (int i=0;i<len;i++) if (i<rev[i]) swap(a[i],a[rev[i]]);
for (int i=1;i<len;i<<=1)
{
int s=(i<<1);
ll wn=ksm(3,(mod-1)/s);
if (t==-1) wn=ksm(wn,mod-2);
for (int j=0;j<len;j+=s)
{
ll w=1;
for (int k=j;k<j+i;k++)
{
ll x=a[k]; ll y=a[k+i]*w%mod;
a[k]=(x+y)%mod; a[k+i]=(x-y+mod)%mod;
w=(w*wn)%mod;
}
}
}
if (t==-1)
{
ll w=ksm(len,mod-2);
for (int i=0;i<len;i++) a[i]=(a[i]*w)%mod;
}
}
void la(int s)
{
k=0;
for (len=1;len<=s*2-1;len<<=1) k++;
for (int i=0;i<len;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
NTT(a,len,1); NTT(b,len,1);
for (int i=0;i<len;i++) a[i]=(a[i]*b[i])%mod;
NTT(a,len,-1);
}
void lalala(int n,int s)
{
for (int i=0;i<(n<<1);i++) a[i]=b[i]=0;
for (int i=0;i<s;i++) a[i]=g[i];
for (int i=0;i<s;i++) b[i]=g[i];
la(s);
for (int i=0;i<n;i++) b[i]=f[i];
la(n);
for (int i=0;i<n;i++) g[i]=(g[i]*2%mod-a[i]+mod)%mod;
}
void solve(int n)
{
if (n==1){
g[0]=ksm(f[0],mod-2);
}
else {
if (n&1) solve(n/2+1); else solve(n/2);
lalala(n,(n&1)?n/2+1:n/2);
}
}
int main()
{
scanf("%lld",&n);
init();
for (int i=0;i<=n;i++) f[i]=ksm(2,((ll)i*(i-1)/2)%(mod-1))*inv[i]%mod;
solve(n+1);
for (int i=0;i<=(n<<2);i++) f[i]=0;
f[0]=0;
for (int i=1;i<=n;i++) f[i]=ksm(2,((ll)i*(i-1)/2)%(mod-1))*inv[i-1]%mod;
k=0;
for (len=1;len<=n*2;len<<=1) k++;
for (int i=0;i<len;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
NTT(g,len,1); NTT(f,len,1);
for (int i=0;i<len;i++) g[i]=(g[i]*f[i])%mod;
NTT(g,len,-1);
if (n==0) cout << 1 << endl; else cout << g[n]*fac[n-1]%mod << endl;
}