[BZOJ3456]城市规划
【题目大意】
求含有n个点有标号的无向联通图的个数(没有重边),n<=130000
方案数对1004535809(479*2^21+1)取模
样例输入
3
样例输出
4
我们考虑递推,$f[i]$表示$i$个点的联通图个数,那么用总数减去不合法的数量。
考虑枚举$1$号点所在的联通块的点数,那么我们可以得到:
$f[n]=2^{\binom{n}{2}}-\sum_{i=1}^{n-1}f[i]*\binom{n-1}{i-1}*2^{\binom{n-i}{2}}$
$\sum_{i=1}^{n}f[i]*\binom{n-1}{i-1}*2^{\binom{n-i}{2}}=2^{\binom{n}{2}}$
$\sum_{i=1}^{n}f[i]*(i-1)!^{-1}*2^{\binom{n-i}{2}}*(n-i)!^{-1}=2^{\binom{n}{2}}*(n-1)!^{-1}$
$$A=\sum_{i=1}^{n}\frac{f[i]}{(i-1)!}*x^i$$
$$B=\sum_{i=0}^{n}\frac{2^{\textrm{C}_{i}^{2}}}{i!}*x^i$$
$$C=\sum_{i=1}^{n}\frac{2^{\textrm{C}_{i}^{2}}}{(i-1)!}*x^i$$
因为A*B=C,也就是A=C*B-1所以求一个多项式逆元,然后NTT就行了
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<complex> 7 using namespace std; 8 typedef int lol; 9 const lol NN=130000; 10 const lol G=3; 11 lol T[8*NN],fac[2*NN],ifac[2*NN],inv[2*NN],cal[2*NN],a[8*NN],b[8*NN],c[8*NN]; 12 lol R[8*NN],Mod=1004535809; 13 lol qpow(lol x,lol y) 14 { 15 lol res=1; 16 while (y) 17 { 18 if (y&1) res=1ll*res*x%Mod; 19 x=1ll*x*x%Mod; 20 y>>=1; 21 } 22 return res; 23 } 24 void NTT(lol *A,lol n,lol L,lol o) 25 {lol i,j,k; 26 lol wn,w,x,y,tmp; 27 for (i=0;i<n;i++) 28 if (i<R[i]) swap(A[i],A[R[i]]); 29 for (i=1;i<n;i<<=1) 30 { 31 wn=qpow(G,(Mod-1)/(i<<1)); 32 if (o==-1) wn=qpow(wn,Mod-2); 33 for (j=0;j<n;j+=(i<<1)) 34 { 35 w=1; 36 for (k=0;k<i;k++,w=1ll*w*wn%Mod) 37 { 38 x=A[j+k];y=1ll*w*A[i+j+k]%Mod; 39 A[j+k]=x+y; 40 if (A[j+k]>=Mod) A[j+k]-=Mod; 41 A[j+k+i]=x-y; 42 if (A[j+k+i]<0) A[j+k+i]+=Mod; 43 } 44 } 45 } 46 if (o==-1) 47 { 48 tmp=qpow(n,Mod-2); 49 for (i=0;i<n;i++) 50 A[i]=1ll*A[i]*tmp%Mod; 51 } 52 } 53 void inverse(lol *A,lol *B,lol n,lol L) 54 {lol i; 55 if (n==1) 56 { 57 B[0]=qpow(A[0],Mod-2); 58 return; 59 } 60 inverse(A,B,n>>1,L-1); 61 for (i=0;i<n<<1;i++) 62 R[i]=(R[i>>1]>>1)|((i&1)<<(L)); 63 for (i=0;i<n;i++) 64 T[i]=A[i],T[n+i]=0; 65 NTT(T,n<<1,L+1,1);NTT(B,n<<1,L+1,1); 66 for (i=0;i<n<<1;i++) 67 T[i]=(1ll*(B[i]<<1)-1ll*B[i]*B[i]%Mod*T[i]%Mod+Mod)%Mod; 68 NTT(T,n<<1,L+1,-1); 69 for (i=0;i<n;i++) 70 B[i]=T[i],B[n+i]=0; 71 } 72 int main() 73 { 74 lol n,lg=0,N,m; 75 lol i; 76 cin>>n; 77 fac[0]=fac[1]=ifac[0]=ifac[1]=inv[1]=cal[0]=cal[1]=1; 78 for (i=2;i<=n;i++) 79 { 80 fac[i]=(1ll*fac[i-1]*i)%Mod; 81 inv[i]=1ll*(Mod-Mod/i)*inv[Mod%i]%Mod; 82 ifac[i]=1ll*ifac[i-1]*inv[i]%Mod; 83 cal[i]=qpow(2,(1ll*i*(i-1)>>1)%(Mod-1)); 84 } 85 b[0]=1; 86 for (i=1;i<=n;i++) 87 a[i]=1ll*cal[i]*ifac[i-1]%Mod; 88 for (i=1;i<=n;i++) 89 b[i]=1ll*cal[i]*ifac[i]%Mod; 90 m=(n<<1); 91 N=1; 92 while (N<=m) N*=2,lg++; 93 inverse(b,c,N,lg); 94 for (i=0;i<N;i++) 95 R[i]=(R[i>>1]>>1)|((i&1)<<(lg-1)); 96 NTT(c,N,lg,1);NTT(a,N,lg,1); 97 for (i=0;i<N;i++) 98 c[i]=1ll*c[i]*a[i]%Mod; 99 NTT(c,N,lg,-1); 100 cout<<1ll*c[n]*fac[n-1]%Mod; 101 }