BZOJ3456: 城市规划 多项式求逆

Posted 小小AI,请多多提携

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ3456: 城市规划 多项式求逆相关的知识,希望对你有一定的参考价值。

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: 城市规划 多项式求逆的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 3456: 城市规划NTT+多项式求逆

bzoj 3456 城市规划 多项式求逆+分治FFT

bzoj3456城市规划(多项式求逆+dp)

bzoj3456城市规划 容斥原理+NTT+多项式求逆

[BZOJ3456]城市规划(生成函数+多项式求逆+多项式求ln)

BZOJ3456:城市规划——题解