Bzoj3456 城市规划
Time Limit: 40 Sec Memory Limit: 256 MB
Submit: 681 Solved: 383
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
在上面那道题中可以得到基本的递推公式 $ F[i]=2^C_{n}^{2} − \sum_{j=1}^{i-1} (C(i-1,j-1)*F[j]*2^C_{i-j}^{2} $
数学问题 动态规划 NTT 生成函数 多项式求逆
蒟蒻自带大常数,TLE简直无情
经过了一番艰苦卓绝的优化,可算是过了。
懒得贴公式了,留坑日后填
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #define LL long long 6 using namespace std; 7 const LL mod=1004535809; 8 const int G=3; 9 const int mxn=1000007; 10 int ansksm[mxn]; 11 int ksm(LL a,LL k){ 12 if(a==3 && k<mxn && ansksm[k])return ansksm[k]; 13 int tmp=k; 14 LL res=1;a%=mod; 15 while(k){ 16 if(k&1)res=(res*a)%mod; 17 a=a*a%mod; 18 k>>=1; 19 } 20 if(a==3)ansksm[tmp]=res; 21 return res; 22 } 23 LL fac[mxn],inv[mxn]; 24 void init(int mxn){ 25 fac[0]=fac[1]=1; 26 inv[0]=inv[1]=1; 27 for(int i=2;i<mxn;i++){ 28 fac[i]=i*fac[i-1]%mod; 29 inv[i]=((-mod/i*inv[mod%i])%mod+mod)%mod; 30 } 31 for(int i=2;i<mxn;i++)inv[i]=inv[i]*inv[i-1]%mod; 32 return; 33 } 34 // 35 int wn[mxn],wr[mxn]; 36 int N,len,rev[mxn]; 37 void NTT(LL *a,int flag){ 38 int i,j,k; 39 for(i=0;i<N;i++)if(i<rev[i])swap(a[i],a[rev[i]]); 40 for(i=1;i<N;i<<=1){ 41 int p=i<<1; 42 // LL gn=ksm(G,(flag==1)?(mod-1)/p:(mod-1)-(mod-1)/p); 43 int gn;gn=(flag==1)?wn[i]:gn=wr[i]; 44 for(j=0;j<N;j+=p){ 45 LL g=1; 46 for(k=0;k<i;k++,g=g*gn%mod){ 47 int x=a[j+k],y=g*a[j+k+i]%mod; 48 a[j+k]=x+y;if(a[j+k]>mod)a[j+k]-=mod; 49 a[j+k+i]=x-y;if(a[j+k+i]<0)a[j+k+i]+=mod; 50 } 51 } 52 } 53 if(flag==-1){ 54 LL INV=ksm(N,mod-2); 55 for(i=0;i<N;i++)a[i]=a[i]*INV%mod; 56 } 57 return; 58 } 59 // 60 LL a[mxn],b[mxn],c[mxn]; 61 void Get_inv(int n,LL *a){ 62 if(n==1){b[0]=1;return;} 63 Get_inv((n+1)>>1,a); 64 // printf("Get %d\n",n); 65 int m=n,i; 66 for(N=1,len=0;N<=m;N<<=1)len++; 67 for(i=0;i<N;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(len-1)); 68 for(i=0;i<n;i++)c[i]=a[i]; 69 for(register int i=n;i<N;i++)c[i]=0; 70 NTT(c,1);NTT(b,1); 71 for(i=0;i<N;i++){ 72 b[i]=(2-(LL)c[i]*b[i]%mod)*b[i]%mod; 73 if(b[i]<0)b[i]+=mod; 74 } 75 NTT(b,-1); 76 for(i=n;i<N;i++)b[i]=0; 77 return; 78 } 79 int n; 80 int main(){ 81 // freopen("in.txt","r",stdin); 82 int i,j; 83 scanf("%d",&n); 84 int ed=n*2; 85 init(ed+1); 86 for (int i=1;i<=ed;i<<=1){ 87 wn[i]=ksm(3,(mod-1)/(i<<1)); 88 wr[i]=ksm(3,(mod-1)-(mod-1)/(i<<1)); 89 } 90 int m=n; 91 for(N=1,len=0;N<=m;N<<=1)len++; 92 a[0]=1; 93 for(i=1;i<=n;i++)a[i]=ksm(2,((LL)i*(i-1)/2)%(mod-1))*inv[i]%mod; 94 Get_inv(N,a); 95 for(N=1,len=0;N<=m;N<<=1)len++; 96 for(i=0;i<N;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(len-1)); 97 for(i=1;i<=n;i++)c[i]=ksm(2,(LL)i*(i-1)/2%(mod-1))*inv[i-1]%mod; 98 c[0]=0;for(i=n+1;i<N;i++)c[i]=0; 99 NTT(b,1);NTT(c,1); 100 for(i=0;i<N;i++)b[i]=b[i]*c[i]%mod; 101 NTT(b,-1); 102 printf("%lld\n",b[n]*fac[n-1]%mod); 103 return 0; 104 }
本文为博主原创文章,转载请注明出处。