bzoj 3456 城市规划 多项式求逆+分治FFT
城市规划
Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 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 }