BZOJ3456: 城市规划 多项式求逆
Posted 小小AI,请多多提携
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ3456: 城市规划 多项式求逆相关的知识,希望对你有一定的参考价值。
3456: 城市规划
Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 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
很经典的多项式问题
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: 城市规划 多项式求逆的主要内容,如果未能解决你的问题,请参考以下文章