• bzoj3456: 城市规划


    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

    方法一:cdq+ntt

    设f[n]为n个点的答案,则

    这就可以做了

    code:

     1 #include<cstdio> 
     2 #include<iostream> 
     3 #include<cmath> 
     4 #include<cstring> 
     5 #include<algorithm> 
     6 #define maxn 262148 
     7 #define mod 1004535809 
     8 #define g 3 
     9 using namespace std; 
    10 typedef long long int64; 
    11 char ch; 
    12 int n; 
    13 int a[maxn],b[maxn],c[maxn],Wn[2][maxn],wn,w,t1,t2; 
    14 int f[maxn],pow2[maxn],fac[maxn],inv_fac[maxn],inv_n[maxn]; 
    15 int re[19][maxn]; 
    16 bool ok; 
    17 inline void read(int &x){ 
    18     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1; 
    19     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); 
    20     if (ok) x=-x; 
    21 } 
    22 inline int rev(int len,int v){ 
    23     int t=0; 
    24     for (int i=0;i<len;i++) t<<=1,t|=v&1,v>>=1; 
    25     return t; 
    26 } 
    27 inline int ksm(int a,int b){ 
    28     int64 t=1; 
    29     for (;b;b>>=1){if (b&1) t=1LL*t*a%mod; a=1LL*a*a%mod;} 
    30     return t; 
    31 } 
    32 inline int ksm(int a,int64 b){ 
    33     int64 t=1; 
    34     for (;b;b>>=1){if (b&1) t=1LL*t*a%mod; a=1LL*a*a%mod;} 
    35     return t; 
    36 } 
    37 inline void ntt(int *a,int n,int len,int op){
    38     for (int i=0,t=re[len][i];i<n;i++,t=re[len][i]) if (i<t) swap(a[i],a[t]); 
    39     for (int s=2;s<=n;s<<=1){ 
    40         wn=Wn[op][s]; 
    41         for (int i=0;i<n;i+=s){ 
    42             w=1; 
    43             for (int j=i;j<i+(s>>1);j++,w=1LL*w*wn%mod){ 
    44                 t1=a[j],t2=1LL*w*a[j+(s>>1)]%mod; 
    45                 a[j]=(t1+t2)%mod,a[j+(s>>1)]=(t1-t2+mod)%mod; 
    46             } 
    47         } 
    48     } 
    49     if (op==1){ 
    50         int x=inv_n[n]; 
    51         for (int i=0;i<n;i++) a[i]=1LL*a[i]*x%mod; 
    52     } 
    53 } 
    54 inline void solve(int l,int r){ 
    55     if (l==r){ 
    56         f[l]=(pow2[l]-(int)(1LL*fac[l-1]*f[l]%mod)+mod)%mod; 
    57         return; 
    58     } 
    59     int m=(l+r)>>1; 
    60     solve(l,m); 
    61     int n=1,len=0; 
    62     while (n<((r-l+1)<<1)) n<<=1,len++; 
    63     for (int i=0;i<n;i++) a[i]=0; 
    64     for (int i=0;i<n;i++) b[i]=0; 
    65     for (int i=l;i<=m;i++) a[i-l]=1LL*f[i]*inv_fac[i-1]%mod; 
    66     for (int i=1;i<r-l+1;i++) b[i]=1LL*pow2[i]*inv_fac[i]%mod; 
    67     ntt(a,n,len,0),ntt(b,n,len,0); 
    68     for (int i=0;i<n;i++) c[i]=1LL*a[i]*b[i]%mod; 
    69     ntt(c,n,len,1); 
    70     for (int i=m+1;i<=r;i++) f[i]=(f[i]+c[i-l])%mod; 
    71     solve(m+1,r); 
    72 } 
    73 void init(){ 
    74     read(n); 
    75     for (int i=1;i<=n;i++) pow2[i]=ksm(2,(1LL*i*(i-1))>>1); 
    76     fac[0]=1; 
    77     for (int i=1;i<=n;i++) fac[i]=1LL*i*fac[i-1]%mod; 
    78     for (int i=0;i<=n;i++) inv_fac[i]=ksm(fac[i],mod-2); 
    79     for (int i=2;i<(n<<2);i<<=1) Wn[0][i]=ksm(g,(mod-1)/i); 
    80     for (int i=2;i<(n<<2);i<<=1) Wn[1][i]=ksm(Wn[0][i],mod-2); 
    81     for (int i=2;i<(n<<2);i<<=1) inv_n[i]=ksm(i,mod-2); 
    82     for (int i=1;(1<<i)<(n<<2);i++){ 
    83         for (int j=0;j<(1<<i);j++) re[i][j]=rev(i,j);   
    84     } 
    85 } 
    86 int main(){ 
    87     init(),solve(1,n); 
    88     printf("%d
    ",f[n]); 
    89     return 0; 
    90 } 

    方法二:多项式的逆元

    http://blog.miskcoo.com/2015/05/bzoj-3456

    如何求多项式的逆元http://blog.miskcoo.com/2015/05/polynomial-inverse

    code:

     1 #include<cstdio> 
     2 #include<iostream> 
     3 #include<cmath> 
     4 #include<cstring> 
     5 #include<algorithm> 
     6 #define maxn 262148 
     7 #define mod 1004535809 
     8 #define g 3 
     9 using namespace std; 
    10 typedef long long int64; 
    11 char ch; 
    12 int m,n,len,N; 
    13 int a[maxn],b[maxn],c[maxn],f[maxn],t[maxn],Wn[2][maxn],wn,w,t1,t2; 
    14 int pow2[maxn],fac[maxn],inv_fac[maxn],inv_n[maxn]; 
    15 int re[19][maxn]; 
    16 bool ok; 
    17 inline void read(int &x){ 
    18     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1; 
    19     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); 
    20     if (ok) x=-x; 
    21 } 
    22 inline int rev(int len,int v){ 
    23     int t=0; 
    24     for (int i=0;i<len;i++) t<<=1,t|=v&1,v>>=1; 
    25     return t; 
    26 } 
    27 inline int ksm(int a,int b){ 
    28     int64 t=1; 
    29     for (;b;b>>=1){if (b&1) t=1LL*t*a%mod; a=1LL*a*a%mod;} 
    30     return t; 
    31 } 
    32 inline int ksm(int a,int64 b){ 
    33     int64 t=1; 
    34     for (;b;b>>=1){if (b&1) t=1LL*t*a%mod; a=1LL*a*a%mod;} 
    35     return t; 
    36 } 
    37 inline void ntt(int *a,int n,int len,int op){ 
    38     for (int i=0,t=re[len][i];i<n;i++,t=re[len][i]) if (i<t) swap(a[i],a[t]); 
    39     for (int s=2;s<=n;s<<=1){ 
    40         wn=Wn[op][s]; 
    41         for (int i=0;i<n;i+=s){ 
    42             w=1; 
    43             for (int j=i;j<i+(s>>1);j++,w=1LL*w*wn%mod){ 
    44                 t1=a[j],t2=1LL*w*a[j+(s>>1)]%mod; 
    45                 a[j]=(t1+t2)%mod,a[j+(s>>1)]=(t1-t2+mod)%mod; 
    46             } 
    47         } 
    48     } 
    49     if (op==1){ 
    50         int x=inv_n[n]; 
    51         for (int i=0;i<n;i++) a[i]=1LL*a[i]*x%mod; 
    52     } 
    53 } 
    54 void init(){ 
    55     read(m),n=m+1,N=1; 
    56     while (N<(n<<1)) N<<=1,len++; 
    57     for (int i=0;i<=n;i++) pow2[i]=ksm(2,(1LL*i*(i-1))>>1); 
    58     fac[0]=1; 
    59     for (int i=1;i<=n;i++) fac[i]=1LL*i*fac[i-1]%mod; 
    60     for (int i=0;i<=n;i++) inv_fac[i]=ksm(fac[i],mod-2); 
    61     for (int i=2;i<(n<<2);i<<=1) Wn[0][i]=ksm(g,(mod-1)/i); 
    62     for (int i=2;i<(n<<2);i<<=1) Wn[1][i]=ksm(Wn[0][i],mod-2); 
    63     for (int i=2;i<(n<<2);i<<=1) inv_n[i]=ksm(i,mod-2); 
    64     for (int i=1;(1<<i)<(n<<2);i++)  for (int j=0;j<(1<<i);j++) re[i][j]=rev(i,j); 
    65     for (int i=0;i<=m;i++) a[i]=1LL*pow2[i]*inv_fac[i]%mod; 
    66     for (int i=1;i<=m;i++) c[i]=1LL*pow2[i]*inv_fac[i-1]%mod; 
    67 } 
    68 void get_inv(int deg,int *a,int *b){ 
    69     if (deg==1){b[0]=ksm(a[0],mod-2);return;} 
    70     get_inv((deg+1)>>1,a,b); 
    71     int n=1,len=0; 
    72     while (n<(deg<<1)) n<<=1,len++; 
    73     for (int i=0;i<deg;i++) t[i]=a[i]; 
    74     for (int i=deg;i<n;i++) t[i]=0; 
    75     ntt(t,n,len,0),ntt(b,n,len,0); 
    76     for (int i=0;i<n;i++) b[i]=(2LL-1LL*t[i]*b[i]%mod+mod)*b[i]%mod; 
    77     ntt(b,n,len,1); 
    78     for (int i=deg;i<n;i++) b[i]=0; 
    79 } 
    80 int main(){ 
    81     init(); 
    82     get_inv(n,a,b); 
    83     ntt(b,N,len,0),ntt(c,N,len,0); 
    84     for (int i=0;i<N;i++) f[i]=1LL*b[i]*c[i]%mod; 
    85     ntt(f,N,len,1); 
    86     printf("%d
    ",(int)(1LL*f[m]*fac[m-1]%mod)); 
    87     return 0; 
    88 }
  • 相关阅读:
    背景颜色的渐变设置--实现丰富多彩的背景效果
    CSS-sprit 雪碧图
    背景图片的相关设置
    关于阿里云图标的使用 iconfont
    HTML四种定位-粘滞定位
    HTML四种定位-固定定位
    HTML四种定位-绝对定位
    HTML四种常见的定位-相对定位
    水平居中
    CentOS8更换国内镜像源
  • 原文地址:https://www.cnblogs.com/chenyushuo/p/4676033.html
Copyright © 2020-2023  润新知