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

城市规划

Time Limit: 40 Sec  Memory Limit: 256 MB
Submit: 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 }

 

posted @ 2018-03-31 14:26  Kaiser-  阅读(176)  评论(0编辑  收藏  举报