Description
求出
n
个点的简单(无重边无自环)无向连通图数目。
方案数
Data Constraint
Solution
设
fn
表示当点数为
n
时的答案,考虑容斥。
考虑不合法情况,枚举一号点所在的连通图的大小
fn=2C2n−∑k=1n−1fk∗Ck−1n−1∗2C2n−k
但这样显然不可做,我们尝试移项,可得
2C2n=∑k=1nfk∗Ck−1n−1∗2C2n−k
把中间的组合数拆开
2C2n=∑k=1nfk∗(n−1)!(k−1)!∗(n−k)!∗2C2n−k
再移一下项,把相关的项移到一起,可得
2C2n(n−1)!=∑k=1nfk(k−1)!∗2C2n−k(n−k)!
设 Gn = 2C2n(n−1)! , Fk = fk(k−1)! , Hk = 2C2n−k(n−k)! ,便可得
Gn=∑k=1nFk∗Hn−k
则有
G(x)=F(x)H(x)
F(x)=G(x)H−1(x)
多项式求逆?!求出 F(x) 便可顺势求出 fn 了。
不会多项式求逆的猛戳 这里。
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,j,l) for(int i=j;i<=l;++i)
#define fd(i,j,l) for(int i=j;i>=l;--i)
using namespace std;
typedef long long ll;
const ll N=14e4,M=8*N,mo=1004535809;
ll t[M],w[M],n,ws,len,jc[N],h[M],g[M],r[M],b[M],tt[M];
ll ksm(ll o,ll t)
{
ll y=1; t=t%(mo-1);
for(;t;t>>=1,o=o*o%mo)
if(t&1)y=y*o%mo;
return y;
}
void NNT(ll *a,int n,int ws,int sig)
{
w[0]=1; w[1]=ksm(3,(mo-1)/n);
fo(i,2,n)w[i]=w[i-1]*w[1]%mo;
fo(i,0,n-1)
{
int p=0;
for(int tp=i,C=0;C<ws;++C,tp>>=1)p=(p<<1)+(tp&1);
t[p]=a[i];
}
ll v,u;
for(int m=2;m<=n;m<<=1)
{
int half=m/2,bei=n/m;
fo(i,0,half-1)
{
v=(sig==1?w[i*bei]:w[n-i*bei]);
for(int j=i;j<n;j+=m)
u=t[j+half]*v%mo,t[j+half]=(t[j]-u+mo)%mo,t[j]=(t[j]+u)%mo;
}
}
fo(i,0,n-1)a[i]=t[i];
if(sig==-1){
ll ny=ksm(n,mo-2);
fo(i,0,n-1)a[i]=a[i]*ny%mo;
}
}
ll C(ll n)
{return n*(n-1)/2;}
void oppsite(ll *a,int cd)
{
tt[0]=ksm(a[0],mo-2);
fo(i,1,4*cd-1)tt[i]=0;
for(int y=1,u=0;y<cd;y<<=1,++u)
{
int len=y*4;
fo(i,0,len-1)r[i]=tt[i];
NNT(r,len,u+2,1);
fo(i,0,len-1)r[i]=r[i]*r[i]%mo;
fo(i,0,len/2-1)b[i]=a[i];
fo(i,len/2,len-1)b[i]=0;
NNT(b,len,u+2,1);
fo(i,0,len-1)b[i]=b[i]*r[i]%mo;
NNT(b,len,u+2,-1);
fo(i,0,2*y-1)tt[i]=(2*tt[i]-b[i]+mo)%mo;
}
fo(i,0,cd-1)a[i]=tt[i];
}
int main()
{
cin>>len;
int ws=0,y=1;
while(y<len*2)y<<=1,++ws;
jc[0]=1; fo(i,1,len)jc[i]=jc[i-1]*ksm(i,mo-2)%mo;
fo(i,1,len)h[i]=ksm(2,C(i))*jc[i-1]%mo;
NNT(h,y,ws,1);
fo(i,0,len)g[i]=ksm(2,C(i))*jc[i]%mo;
oppsite(g,y);
NNT(g,y,ws,1);
fo(i,0,y-1)g[i]=g[i]*h[i]%mo;
NNT(g,y,ws,-1);
ll ans=g[len];
fo(i,2,len-1)ans=ans*i%mo;
printf("%lld",ans);
}