洛谷 P4841 城市規劃 解題報告
阿新 • • 發佈:2018-12-26
P4841 城市規劃
題意
n個有標號點的簡單(無重邊無自環)無向連通圖數目.
輸入輸出格式
輸入格式:
僅一行一個整數\(n(\le 130000)\)
輸出格式:
僅一行一個整數, 為方案數 \(\bmod 1004535809\).
設\(g_i\)表示\(i\)個點的圖的數目,\(f_i\)表示\(i\)個點聯通圖的個數
\[ g_n=f_n+\sum_{i=1}^{n-1}f_i\binom{n-1}{i-1}g^{n-i} \]
意義是聯通圖+非聯通圖,關於非聯通圖的方案,列舉1號點所在聯通塊然後剩下的隨意構圖,不連通。
顯然有\(g_n=2^{\binom{n}{2}}\)
\[ \begin{aligned} 2^{\binom{n}{2}}&=\sum_{i=1}^nf_i\binom{n-1}{i-1}2^{\binom{n-i}{2}}\\ \frac{2^{\binom{n}{2}}}{(n-1)!}&=\sum_{i=1}^n\frac{f_i}{(i-1)!}\frac{2^{\binom{n-i}{2}}}{(n-i)!} \end{aligned} \]
然後令
\[ F(i)=\frac{f_i}{(i-1)!},G(i)=\frac{2^{\binom{i}{2}}}{(i-1)!},H(i)=\frac{2^{\binom{i}{2}}}{i!} \]
顯然有
\[ G=F*H \]
對\(H\)求個逆就可以了。
一些關於意義的邊界問題可以試試,反正不是0就是1..
調這個題的時候因為把指數給膜了,掛了20年...
Code:
#include <cstdio> #include <algorithm> const int mod=1004535809,Gi=334845270; const int N=(1<<20)+10; #define mul(a,b) (1ll*(a)*(b)%mod) #define add(a,b) ((a+b)%mod) int fac[N],inv[N],A[N],B[N],t[2][N],G[N],H[N],turn[N],n,len,L; int qp(int d,int k){int f=1;while(k){if(k&1)f=mul(f,d);d=mul(d,d),k>>=1;}return f;} void NTT(int *a,int typ) { for(int i=1;i<len;i++) if(i<turn[i]) std::swap(a[i],a[turn[i]]); for(int le=1;le<len;le<<=1) { int wn=qp(typ?3:Gi,(mod-1)/(le<<1)); for(int p=0;p<len;p+=le<<1) { int w=1; for(int i=p;i<p+le;i++,w=mul(w,wn)) { int tx=a[i],ty=mul(w,a[i+le]); a[i]=add(tx,ty); a[i+le]=add(tx,mod-ty); } } } if(!typ) { int inv=qp(len,mod-2); for(int i=0;i<len;i++) a[i]=mul(a[i],inv); } } void polymul(int *a,int *b) { for(int i=0;i<len;i++) A[i]=B[i]=0; for(int i=0;i<len>>1;i++) A[i]=a[i],B[i]=b[i]; NTT(A,1),NTT(B,1); for(int i=0;i<len;i++) A[i]=mul(A[i],B[i]); NTT(A,0); for(int i=0;i<len;i++) a[i]=A[i]; } void init() { for(int i=1;i<len;i++) turn[i]=turn[i>>1]>>1|(i&1)<<L; } void polyinv(int *a,int n) { int cur=0;t[cur][0]=qp(a[0],mod-2); len=1,L=-1; while(len<=n<<2) { len<<=1,++L,cur^=1,init(); for(int i=0;i<len>>1;i++) t[cur][i]=add(t[cur^1][i],t[cur^1][i]); polymul(t[cur^1],t[cur^1]); polymul(t[cur^1],a); for(int i=0;i<len;i++) t[cur][i]=add(t[cur][i],mod-t[cur^1][i]); } for(int i=0;i<=n;i++) a[i]=t[cur][i]; } int main() { scanf("%d",&n); fac[0]=1;for(int i=1;i<=n;i++) fac[i]=mul(fac[i-1],i); inv[n]=qp(fac[n],mod-2); for(int i=n-1;~i;i--) inv[i]=mul(inv[i+1],i+1); for(int i=1;i<=n;i++) G[i]=mul(qp(2,1ll*i*(i-1)/2%(mod-1)),inv[i-1]); for(int i=0;i<=n;i++) H[i]=mul(qp(2,1ll*i*(i-1)/2%(mod-1)),inv[i]);//這個mod-1調了本菜雞20years polyinv(H,n); polymul(G,H); printf("%d\n",mul(G[n],fac[n-1])); return 0; }
2018.12.26