[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 }

 

posted @ 2018-01-29 11:46  Z-Y-Y-S  阅读(475)  评论(6编辑  收藏  举报