1. 程式人生 > >bzoj 3456 城市規劃 多項式求逆+分治FFT

bzoj 3456 城市規劃 多項式求逆+分治FFT

desc esc swap 存在 line tor memcpy status geo

城市規劃

Time Limit: 40 Sec Memory Limit: 256 MB
Submit: 1091 Solved: 629
[Submit][Status][Discuss]

Description

剛剛解決完電力網絡的問題, 阿貍又被領導的任務給難住了.
剛才說過, 阿貍的國家有n個城市, 現在國家需要在某些城市對之間建立一些貿易路線, 使得整個國家的任意兩個城市都直接或間接的連通. 為了省錢, 每兩個城市之間最多只能有一條直接的貿易路徑. 對於兩個建立路線的方案, 如果存在一個城市對, 在兩個方案中是否建立路線不一樣, 那麽這兩個方案就是不同的, 否則就是相同的. 現在你需要求出一共有多少不同的方案.

好了, 這就是困擾阿貍的問題. 換句話說, 你需要求出n個點的簡單(無重邊無自環)無向連通圖數目.
由於這個數字可能非常大, 你只需要輸出方案數mod 1004535809(479 * 2 ^ 21 + 1)即可.

Input

僅一行一個整數n(<=130000)

Output

僅一行一個整數, 為方案數 mod 1004535809.

Sample Input

3

Sample Output

4

HINT

對於 100%的數據, n <= 130000

題解:http://blog.miskcoo.com/2015/05/bzoj-3456

    我沒什麽好說的。

  1 #include<cstring>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<iostream>
  5 #include<algorithm>
  6 
  7 #define ll long long
  8 #define N 262144
  9 #define mod 1004535809
 10 using namespace std;
 11 inline int read()
 12 {
13 int x=0,f=1;char ch=getchar(); 14 while(!isdigit(ch)){if(ch==-)f=-1;ch=getchar();} 15 while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-0;ch=getchar();} 16 return x*f; 17 } 18 19 int n; 20 ll Factor[N],Inv_Fac[N]; 21 ll G[N],inv_fac[N],dao_G[N]; 22 int rev[N]; 23 24 ll fast_pow(ll x,ll y,ll MOD) 25 { 26 ll ret=1; 27 while(y) 28 { 29 if(y&1)ret=(ret*x)%MOD; 30 x=(x*x)%MOD; 31 y>>=1; 32 } 33 return ret; 34 } 35 void init() 36 { 37 Factor[0]=1,Inv_Fac[0]=1; 38 for(int i=1;i<=n;i++) 39 { 40 Factor[i]=Factor[i-1]*i%mod; 41 Inv_Fac[i]=fast_pow(Factor[i],mod-2,mod); 42 } 43 } 44 void NTT(ll *a,int num,int f) 45 { 46 for (int i=0;i<num;i++)if(i<rev[i])swap(a[i],a[rev[i]]); 47 for (int i=1;i<num;i<<=1) 48 { 49 ll wn=fast_pow(3,(mod-1)/(i<<1),mod); 50 for(int j=0;j<num;j+=(i<<1)) 51 { 52 ll w=1; 53 for (int k=0;k<i;(w*=wn)%=mod,k++) 54 { 55 ll x=a[j+k],y=w*a[j+k+i]%mod; 56 a[j+k]=(x+y>=mod)?x+y-mod:x+y;a[j+k+i]=(x-y<0)?x-y+mod:x-y; 57 } 58 } 59 } 60 if(f==-1) 61 { 62 for (int i=1;i<num/2;i++)swap(a[i],a[num-i]); 63 ll inv=fast_pow(num,mod-2,mod); 64 for (int i=0;i<num;i++)(a[i]*=inv)%=mod; 65 } 66 } 67 void Get_Inv(ll *a,ll *b,int n) 68 { 69 static ll temp[N]; 70 if(n==1) 71 { 72 b[0]=fast_pow(a[0],mod-2,mod); 73 return ; 74 } 75 Get_Inv(a,b,n>>1); 76 memcpy(temp,a,sizeof(a[0])*n); 77 memset(temp+n,0,sizeof(a[0])*n); 78 int m=n,L=0,nn=n; 79 for(n=1;n<=m;n<<=1)L++;if (L) L--; 80 for(int i=0;i<n;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<L); 81 NTT(temp,n,1),NTT(b,n,1); 82 for(int i=0;i<n;i++) 83 temp[i]=b[i]*(((2ll-temp[i]*b[i]%mod)%mod+mod)%mod)%mod; 84 NTT(temp,n,-1); 85 for(int i=0;i<(n>>1);i++)b[i]=temp[i]; 86 memset(b+nn,0,sizeof(b[0])*nn); 87 } 88 int main() 89 { 90 n=read(),init(); 91 for(int i=0;i<=n;i++) 92 { 93 if(i<2)G[i]=1; 94 else G[i]=fast_pow(2,(ll)i*(i-1)/2,mod)*Inv_Fac[i]%mod; 95 } 96 for(int i=1;i<=n;i++) dao_G[i-1]=G[i]*i%mod;dao_G[n]=0; 97 int l;for(l=1;l<=n;l<<=1); 98 Get_Inv(G,inv_fac,l); 99 int m=n,L=0; 100 for(n=1;n<=m;n<<=1)L++;if (L) L--; 101 for(int i=0;i<n;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<L); 102 NTT(dao_G,n,1),NTT(inv_fac,n,1); 103 for(int i=0;i<n;i++) 104 dao_G[i]=(inv_fac[i]*dao_G[i])%mod; 105 NTT(dao_G,n,-1); 106 printf("%lld\n",(dao_G[m-1]*fast_pow(m,mod-2,mod)%mod)*Factor[m]%mod); 107 }

bzoj 3456 城市規劃 多項式求逆+分治FFT