zoukankan      html  css  js  c++  java
  • [BZOJ3456]城市规划(生成函数+多项式求逆+多项式求ln)

    城市规划

    时间限制:40s      空间限制:256MB

    题目描述

     刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了.
     刚才说过, 阿狸的国家有n个城市, 现在国家需要在某些城市对之间建立一些贸易路线, 使得整个国家的任意两个城市都直接或间接的连通. 为了省钱, 每两个城市之间最多只能有一条直接的贸易路径. 对于两个建立路线的方案, 如果存在一个城市对, 在两个方案中是否建立路线不一样, 那么这两个方案就是不同的, 否则就是相同的. 现在你需要求出一共有多少不同的方案.
     好了, 这就是困扰阿狸的问题. 换句话说, 你需要求出n个点的简单(无重边无自环)无向连通图数目.
     由于这个数字可能非常大, 你只需要输出方案数mod 1004535809(479 * 2 ^ 21 + 1)即可.


    输入格式

     仅一行一个整数n(<=130000)
     


    输出格式

     仅一行一个整数, 为方案数 mod 1004535809.
     


    样例输入

     3
    
    

    样例输出

     4
    

    提示

     对于 100%的数据, n <= 130000


    题目来源

    没有写明来源

    传说中FFT应用的最高境界?现在恐怕配不上这个称号了。

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

    解法一:

    先按照惯例减弱条件限制,不要求图连通,再将连通和不联通之间的递推关系式化成卷积的形式。最后直接上生成函数,在模$x^{n+1}$下求多项式的逆元即可。

    次数界放宽!递归求逆元的时候次数界要放成两倍!

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define rep(i,l,r) for (int i=l; i<=r; i++)
     4 using namespace std;
     5 
     6 const int N=300100,mod=1004535809,g=3;
     7 int n,m,a[N],b[N],lg[N<<1],fac[N],fin[N],tmp[N],c[N],b1[N],rev[N];
     8 
     9 int ksm(int a,int b){
    10     int res;
    11     for (res=1; b; a=1ll*a*a%mod,b>>=1)
    12         if (b&1) res=1ll*res*a%mod;
    13     return res;
    14 }
    15 
    16 void DFT(int a[],int n,int f){
    17     for (int i=0; i<n; i++) if (i<rev[i]) swap(a[i],a[rev[i]]);
    18     for (int i=1; i<n; i<<=1){
    19         int wn=ksm(g,(f==1) ? (mod-1)/(i<<1) : (mod-1)-(mod-1)/(i<<1));
    20         for (int p=i<<1,j=0; j<n; j+=p){
    21             int w=1;
    22             for (int k=0; k<i; k++,w=1ll*w*wn%mod){
    23                 int x=a[j+k],y=1ll*w*a[i+j+k]%mod; a[j+k]=(x+y)%mod; a[i+j+k]=(x-y+mod)%mod;
    24             }
    25         }
    26     }
    27     if (f==1) return;
    28     int inv=ksm(n,mod-2);
    29     for (int i=0; i<n; i++) a[i]=1ll*a[i]*inv%mod;
    30 }
    31 
    32 void get(int a[],int b[],int l){
    33     if (l==1){ b[0]=ksm(a[0],mod-2); return ;}
    34     get(a,b,l>>1); int n=l<<1;
    35     for (int i=0; i<l; i++) tmp[i]=a[i],tmp[i+l]=0;
    36     
    37     for (int i=0; i<n; i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(lg[n]-1));
    38     DFT(tmp,n,1); DFT(b,n,1);
    39     for (int i=0; i<n; i++) tmp[i]=1ll*b[i]*(2-1ll*tmp[i]*b[i]%mod+mod)%mod;
    40     DFT(tmp,n,-1);
    41     
    42     for (int i=0; i<l; i++) b[i]=tmp[i],b[i+l]=0;
    43 }
    44 
    45 int main(){
    46     freopen("bzoj3456.in","r",stdin);
    47     freopen("bzoj3456.out","w",stdout);
    48     scanf("%d",&n); fac[0]=fin[0]=1; lg[1]=0;
    49     rep(i,2,n<<2) lg[i]=lg[i>>1]+1;
    50     rep(i,1,n) fac[i]=1ll*fac[i-1]*i%mod;
    51     fin[n]=ksm(fac[n],mod-2);
    52     for (int i=n-1; i; i--) fin[i]=1ll*fin[i+1]*(i+1)%mod;
    53     rep(i,0,n) b[i]=1ll*ksm(2,1ll*i*(i-1)/2%(mod-1))*fin[i]%mod;
    54     rep(i,1,n) c[i]=1ll*ksm(2,1ll*i*(i-1)/2%(mod-1))*fin[i-1]%mod;
    55     for (m=1; m<=n; m<<=1); get(b,b1,m);
    56     DFT(c,m<<1,1); DFT(b1,m<<1,1);
    57     for (int i=0; i<(m<<1); i++) c[i]=1ll*c[i]*b1[i]%mod;
    58     DFT(c,m<<1,-1); printf("%lld
    ",1ll*c[n]*fac[n-1]%mod);
    59     return 0;
    60 }

     解法二:指数型生成函数

    惊奇地发现正好要求的函数可以放在exp的指数上,多项式求ln即可。

    形式幂级数什么的真是太有意思了。

    https://blog.csdn.net/u014609452/article/details/56291323

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define rep(i,l,r) for (int i=l; i<=r; i++)
     4 using namespace std;
     5 
     6 const int N=600100,mod=1004535809,g=3;
     7 int n,m,G[N],G1[N],invG[N],lg[N<<1],fac[N],fin[N],tmp[N],c[N],b1[N],rev[N];
     8 
     9 int ksm(int a,int b){
    10     int res;
    11     for (res=1; b; a=1ll*a*a%mod,b>>=1)
    12         if (b&1) res=1ll*res*a%mod;
    13     return res;
    14 }
    15 
    16 void DFT(int a[],int n,int f){
    17     for (int i=0; i<n; i++) if (i<rev[i]) swap(a[i],a[rev[i]]);
    18     for (int i=1; i<n; i<<=1){
    19         int wn=ksm(g,(f==1) ? (mod-1)/(i<<1) : (mod-1)-(mod-1)/(i<<1));
    20         for (int p=i<<1,j=0; j<n; j+=p){
    21             int w=1;
    22             for (int k=0; k<i; k++,w=1ll*w*wn%mod){
    23                 int x=a[j+k],y=1ll*w*a[i+j+k]%mod; a[j+k]=(x+y)%mod; a[i+j+k]=(x-y+mod)%mod;
    24             }
    25         }
    26     }
    27     if (f==1) return;
    28     int inv=ksm(n,mod-2);
    29     for (int i=0; i<n; i++) a[i]=1ll*a[i]*inv%mod;
    30 }
    31 
    32 void get(int a[],int b[],int l){
    33     if (l==1){ b[0]=ksm(a[0],mod-2); return ;}
    34     get(a,b,l>>1); int n=l<<1;
    35     for (int i=0; i<l; i++) tmp[i]=a[i],tmp[i+l]=0;
    36     
    37     for (int i=0; i<n; i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(lg[n]-1));
    38     DFT(tmp,n,1); DFT(b,n,1);
    39     for (int i=0; i<n; i++) tmp[i]=1ll*b[i]*(2-1ll*tmp[i]*b[i]%mod+mod)%mod;
    40     DFT(tmp,n,-1);
    41     
    42     for (int i=0; i<l; i++) b[i]=tmp[i],b[i+l]=0;
    43 }
    44 
    45 int main(){
    46     freopen("bzoj3456.in","r",stdin);
    47     freopen("bzoj3456.out","w",stdout);
    48     scanf("%d",&n); fac[0]=fin[0]=1; lg[1]=0;
    49     rep(i,2,n<<3) lg[i]=lg[i>>1]+1;
    50     rep(i,1,n) fac[i]=1ll*fac[i-1]*i%mod;
    51     fin[n]=ksm(fac[n],mod-2);
    52     for (int i=n-1; i; i--) fin[i]=1ll*fin[i+1]*(i+1)%mod;
    53     
    54     G[0]=G[1]=1; G1[n]=0;
    55     rep(i,0,n) G[i]=1ll*ksm(2,(1ll*i*(i-1)/2)%(mod-1))*fin[i]%mod;
    56     rep(i,1,n) G1[i-1]=1ll*G[i]*i%mod;
    57     
    58     for (m=1; m<=n; m<<=1); get(G,invG,m); m<<=1;
    59     DFT(G1,m,1); DFT(invG,m,1);
    60     for (int i=0; i<m; i++) G1[i]=1ll*invG[i]*G1[i]%mod;
    61     DFT(G1,m,-1);
    62     
    63     printf("%lld
    ",(1ll*G1[n-1]*ksm(n,mod-2)%mod)*fac[n]%mod);
    64     return 0;
    65 }
  • 相关阅读:
    [转载]PHP中PSR-[0-4]规范
    Git忽略规则及.gitignore规则不生效的解决办法
    nginx配置tp5的pathinfo模式并隐藏后台入口文件
    php过滤&nbsp;字符
    使用ajax的post方式下载excel
    scws简单中文分词
    php的api及登录的权限验证
    对钩子的理解
    基于角色的权限控制
    微信开发之SVN提交代码与FTP同步到apache的根目录
  • 原文地址:https://www.cnblogs.com/HocRiser/p/8687578.html
Copyright © 2011-2022 走看看