BZOJ 3456 3456: 城市规划 (NTT+多项式求逆)
Posted konjak魔芋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 3456 3456: 城市规划 (NTT+多项式求逆)相关的知识,希望对你有一定的参考价值。
3456: 城市规划
Time Limit: 40 Sec Memory Limit: 256 MB
Submit: 658 Solved: 364Description
刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了.
刚才说过, 阿狸的国家有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
【分析】
又是看题解和抄代码的好季节。。。
呵呵呵
【关于多项式求逆看这里
转自:http://blog.miskcoo.com/2015/05/bzoj-3456
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define Mod 1004535809 8 #define LL long long 9 #define Maxn 130000*4 10 const int G=3; 11 12 int fac[Maxn],F[Maxn],H[Maxn],V[Maxn]; 13 14 int qpow(int x,int b) 15 { 16 int ans=1; 17 while(b) 18 { 19 if(b&1) ans=1LL*ans*x%Mod; 20 x=1LL*x*x%Mod; 21 b>>=1; 22 } 23 return ans; 24 } 25 26 int R[Maxn]; 27 void NTT(int *a,int nn,int t) 28 { 29 for(int i=0,j=0;i<nn;i++) 30 { 31 if(i>j) swap(a[i],a[j]); 32 for(int l=(nn>>1);(j^=l)<l;l>>=1); 33 } 34 for(int i=1;i<nn;i<<=1) 35 { 36 int wn=qpow(G,(Mod-1)/(i<<1)); 37 for(int j=0;j<nn;j+=(i<<1)) 38 { 39 int w=1; 40 for(int k=0;k<i;k++) 41 { 42 int x=a[j+k],y=1LL*w*a[j+k+i]%Mod; 43 a[j+k]=(x+y)%Mod;a[j+k+i]=((x-y)%Mod+Mod)%Mod; 44 w=1LL*w*wn%Mod; 45 } 46 } 47 } 48 if(t==-1) 49 { 50 int inv=qpow(nn,Mod-2); 51 reverse(a+1,a+nn); 52 for(int i=0;i<=nn;i++) a[i]=1LL*a[i]*inv%Mod; 53 } 54 } 55 56 // int temp[Maxn]; 57 void get_inv(int *a,int *b,int len) 58 { 59 static int temp[Maxn]; 60 if(len==1) 61 { 62 b[0]=qpow(a[0],Mod-2); 63 b[1]=0; 64 return; 65 } 66 get_inv(a,b,len>>1); 67 for(int i=0;i<=len;i++) temp[i]=a[i]; 68 for(int i=len+1;i<=len<<1;i++) temp[i]=0; 69 // memcpy(temp,a,sizeof(int)*len); 70 // memset(temp+len,0,sizeof(int)*len); 71 NTT(temp,len<<1,1),NTT(b,len<<1,1); 72 for(int i=0;i<(len<<1);i++) b[i]=1LL*b[i]*(2-1LL*temp[i]*b[i]%Mod+Mod)%Mod; 73 NTT(b,len<<1,-1); 74 memset(b+len,0,sizeof(int)*len); 75 } 76 77 78 int n,m; 79 void fal() 80 { 81 for(int i=1;i<=m;i++) H[i-1]=1LL*F[i]*i%Mod; 82 get_inv(F,V,m); 83 NTT(H,m,1);NTT(V,m,1); 84 for(int i=0;i<=m;i++) F[i]=1LL*H[i]*V[i]%Mod; 85 NTT(F,m,-1); 86 for(int i=n;i>=1;i--) F[i]=1LL*F[i-1]*qpow(i,Mod-2)%Mod; 87 } 88 89 int main() 90 { 91 scanf("%d",&n); 92 m=1;while(m<=2*n) m<<=1; 93 fac[0]=1;for(int i=1;i<=n;i++) fac[i]=1LL*fac[i-1]*i%Mod; 94 F[0]=1; 95 for(int i=1;i<=n;i++) 96 { 97 F[i]=1LL*qpow(2,1LL*i*(i-1)/2%(Mod-1))*qpow(fac[i],Mod-2)%Mod; 98 } 99 fal(); 100 F[n]=1LL*F[n]*fac[n]%Mod; 101 printf("%d\\n",F[n]); 102 return 0; 103 }
尝试了好多遍,发现不用static 似乎是不行的?
2017-04-15 11:54:42
以上是关于BZOJ 3456 3456: 城市规划 (NTT+多项式求逆)的主要内容,如果未能解决你的问题,请参考以下文章