1. 程式人生 > >BZOJ3456: 城市規劃 多項式求逆

BZOJ3456: 城市規劃 多項式求逆

sca 如果 數據 fpm void its bzoj3456 limit set

3456: 城市規劃

Time Limit: 40 Sec Memory Limit: 256 MB
Submit: 798 Solved: 451
[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

Source

[Submit][Status][Discuss]

很經典的多項式問題

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 
  4 typedef long long ll;
  5 
  6 const int maxn=300000
,mod=1004535809; 7 8 ll fpm(ll a,ll b){ 9 ll ret=1ll; 10 for(;b;b>>=1,a=a*a%mod) 11 if(b&1)ret=ret*a%mod; 12 return ret; 13 } 14 15 ll fac[maxn],ifac[maxn]; 16 17 void init(){ 18 fac[0]=1; 19 for(int i=1;i<maxn>>1;++i){ 20 fac[i]=fac[i-1
]*i%mod; 21 } 22 ifac[(maxn>>1)-1]=fpm(fac[(maxn>>1)-1],mod-2); 23 for(int i=(maxn>>1)-1;i;--i){ 24 ifac[i-1]=ifac[i]*i%mod; 25 } 26 } 27 28 int A[maxn],B[maxn]; 29 int n,m; 30 31 void fft(int *a,int n,int on){ 32 static int tmp[maxn]; 33 if(n==1)return; 34 for(int i=0;i<n;++++i){ 35 tmp[i>>1]=a[i]; 36 tmp[i+n>>1]=a[i+1]; 37 } 38 39 memcpy(a,tmp,sizeof(a[0])*n); 40 int *l=a,*r=a+(n>>1); 41 fft(l,n>>1,on); 42 fft(r,n>>1,on); 43 44 int wn=1,w=fpm(3,(1ll*(mod-1)/n*on)%(mod-1)); 45 for(int i=0;i<n>>1;++i){ 46 tmp[i]=(1ll*wn*r[i]%mod+1ll*l[i])%mod; 47 tmp[i+(n>>1)]=(1ll*l[i]+mod-1ll*wn*r[i]%mod)%mod; 48 wn=1ll*wn*w%mod; 49 } 50 memcpy(a,tmp,sizeof(a[0])*n); 51 } 52 53 void mul(int *a,int *b,int m){ 54 55 fft(a,m,1);fft(b,m,1); 56 for(int i=0;i<m;++i){ 57 a[i]=1ll*a[i]*b[i]%mod; 58 } 59 fft(a,m,mod-2); 60 for(int i=0,inv=fpm(m,mod-2);i<m;++i){ 61 a[i]=1ll*a[i]*inv%mod; 62 } 63 } 64 65 void the_inv(int *a,int *b,int n){ 66 fft(a,n,1); 67 fft(b,n,1); 68 for(int i=0;i<n;++i) 69 a[i]=1ll*(2ll-1ll*a[i]*b[i]%mod+mod)%mod*b[i]%mod; 70 fft(a,n,mod-2); 71 for(int i=0,inv=fpm(n,mod-2);i<n;++i){ 72 b[i]=1ll*a[i]*inv%mod; 73 } 74 } 75 76 void Get_inv(int *a,int *b,int n){ 77 static int tmp[maxn]; 78 if(n==1){ 79 b[0]=fpm(a[0],mod-2); 80 return; 81 } 82 Get_inv(a,b,n>>1); 83 memcpy(tmp,a,sizeof(a[0])*n); 84 memset(tmp+n,0,sizeof(a[0])*n); 85 the_inv(tmp,b,n<<1); 86 memset(b+n,0,sizeof(a[0])*n); 87 } 88 89 int main(){ 90 init(); 91 scanf("%d",&n); 92 93 for(m=1;m<=n<<1;m<<=1); 94 95 for(int i=0;i<=n;++i){ 96 A[i]=fpm(2,(1ll*i*(i-1)>>1)%(mod-1)); 97 A[i]=A[i]*ifac[i]%mod; 98 } 99 Get_inv(A,B,m>>1); 100 101 A[0]=0; 102 for(int i=1;i<=n;++i){ 103 A[i]=fpm(2,(1ll*i*(i-1)>>1)%(mod-1)); 104 A[i]=A[i]*ifac[i-1]%mod; 105 } 106 mul(A,B,m); 107 108 cout<<1ll*A[n]*fac[n-1]%mod<<endl; 109 return 0; 110 }

BZOJ3456: 城市規劃 多項式求逆