城市规划

时间限制: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}$下求多项式的逆元即可。

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

 #include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
using namespace std; const int N=,mod=,g=;
int n,m,a[N],b[N],lg[N<<],fac[N],fin[N],tmp[N],c[N],b1[N],rev[N]; int ksm(int a,int b){
int res;
for (res=; b; a=1ll*a*a%mod,b>>=)
if (b&) res=1ll*res*a%mod;
return res;
} void DFT(int a[],int n,int f){
for (int i=; i<n; i++) if (i<rev[i]) swap(a[i],a[rev[i]]);
for (int i=; i<n; i<<=){
int wn=ksm(g,(f==) ? (mod-)/(i<<) : (mod-)-(mod-)/(i<<));
for (int p=i<<,j=; j<n; j+=p){
int w=;
for (int k=; k<i; k++,w=1ll*w*wn%mod){
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;
}
}
}
if (f==) return;
int inv=ksm(n,mod-);
for (int i=; i<n; i++) a[i]=1ll*a[i]*inv%mod;
} void get(int a[],int b[],int l){
if (l==){ b[]=ksm(a[],mod-); return ;}
get(a,b,l>>); int n=l<<;
for (int i=; i<l; i++) tmp[i]=a[i],tmp[i+l]=; for (int i=; i<n; i++) rev[i]=(rev[i>>]>>)|((i&)<<(lg[n]-));
DFT(tmp,n,); DFT(b,n,);
for (int i=; i<n; i++) tmp[i]=1ll*b[i]*(-1ll*tmp[i]*b[i]%mod+mod)%mod;
DFT(tmp,n,-); for (int i=; i<l; i++) b[i]=tmp[i],b[i+l]=;
} int main(){
freopen("bzoj3456.in","r",stdin);
freopen("bzoj3456.out","w",stdout);
scanf("%d",&n); fac[]=fin[]=; lg[]=;
rep(i,,n<<) lg[i]=lg[i>>]+;
rep(i,,n) fac[i]=1ll*fac[i-]*i%mod;
fin[n]=ksm(fac[n],mod-);
for (int i=n-; i; i--) fin[i]=1ll*fin[i+]*(i+)%mod;
rep(i,,n) b[i]=1ll*ksm(,1ll*i*(i-)/%(mod-))*fin[i]%mod;
rep(i,,n) c[i]=1ll*ksm(,1ll*i*(i-)/%(mod-))*fin[i-]%mod;
for (m=; m<=n; m<<=); get(b,b1,m);
DFT(c,m<<,); DFT(b1,m<<,);
for (int i=; i<(m<<); i++) c[i]=1ll*c[i]*b1[i]%mod;
DFT(c,m<<,-); printf("%lld\n",1ll*c[n]*fac[n-]%mod);
return ;
}

解法二:指数型生成函数

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

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

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

 #include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
using namespace std; const int N=,mod=,g=;
int n,m,G[N],G1[N],invG[N],lg[N<<],fac[N],fin[N],tmp[N],c[N],b1[N],rev[N]; int ksm(int a,int b){
int res;
for (res=; b; a=1ll*a*a%mod,b>>=)
if (b&) res=1ll*res*a%mod;
return res;
} void DFT(int a[],int n,int f){
for (int i=; i<n; i++) if (i<rev[i]) swap(a[i],a[rev[i]]);
for (int i=; i<n; i<<=){
int wn=ksm(g,(f==) ? (mod-)/(i<<) : (mod-)-(mod-)/(i<<));
for (int p=i<<,j=; j<n; j+=p){
int w=;
for (int k=; k<i; k++,w=1ll*w*wn%mod){
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;
}
}
}
if (f==) return;
int inv=ksm(n,mod-);
for (int i=; i<n; i++) a[i]=1ll*a[i]*inv%mod;
} void get(int a[],int b[],int l){
if (l==){ b[]=ksm(a[],mod-); return ;}
get(a,b,l>>); int n=l<<;
for (int i=; i<l; i++) tmp[i]=a[i],tmp[i+l]=; for (int i=; i<n; i++) rev[i]=(rev[i>>]>>)|((i&)<<(lg[n]-));
DFT(tmp,n,); DFT(b,n,);
for (int i=; i<n; i++) tmp[i]=1ll*b[i]*(-1ll*tmp[i]*b[i]%mod+mod)%mod;
DFT(tmp,n,-); for (int i=; i<l; i++) b[i]=tmp[i],b[i+l]=;
} int main(){
freopen("bzoj3456.in","r",stdin);
freopen("bzoj3456.out","w",stdout);
scanf("%d",&n); fac[]=fin[]=; lg[]=;
rep(i,,n<<) lg[i]=lg[i>>]+;
rep(i,,n) fac[i]=1ll*fac[i-]*i%mod;
fin[n]=ksm(fac[n],mod-);
for (int i=n-; i; i--) fin[i]=1ll*fin[i+]*(i+)%mod; G[]=G[]=; G1[n]=;
rep(i,,n) G[i]=1ll*ksm(,(1ll*i*(i-)/)%(mod-))*fin[i]%mod;
rep(i,,n) G1[i-]=1ll*G[i]*i%mod; for (m=; m<=n; m<<=); get(G,invG,m); m<<=;
DFT(G1,m,); DFT(invG,m,);
for (int i=; i<m; i++) G1[i]=1ll*invG[i]*G1[i]%mod;
DFT(G1,m,-); printf("%lld\n",(1ll*G1[n-]*ksm(n,mod-)%mod)*fac[n]%mod);
return ;
}

[BZOJ3456]城市规划(生成函数+多项式求逆+多项式求ln)的更多相关文章

  1. FFT模板 生成函数 原根 多项式求逆 多项式开根

    FFT #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> ...

  2. NTT+多项式求逆+多项式开方(BZOJ3625)

    定义多项式$h(x)$的每一项系数$h_i$,为i在c[1]~c[n]中的出现次数. 定义多项式$f(x)$的每一项系数$f_i$,为权值为i的方案数. 通过简单的分析我们可以发现:$f(x)=\fr ...

  3. 【BZOJ3456】轩辕朗的城市规划 无向连通图计数 CDQ分治 FFT 多项式求逆 多项式ln

    题解 分治FFT 设\(f_i\)为\(i\)个点组成的无向图个数,\(g_i\)为\(i\)个点组成的无向连通图个数 经过简单的推导(枚举\(1\)所在的连通块大小),有: \[ f_i=2^{\f ...

  4. bzoj 3456 城市规划——分治FFT / 多项式求逆 / 多项式求ln

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3456 分治FFT: 设 dp[ i ] 表示 i 个点时连通的方案数. 考虑算补集:连通的方 ...

  5. 2019.01.01 bzoj3625:小朋友和二叉树(生成函数+多项式求逆+多项式开方)

    传送门 codeforces传送门codeforces传送门codeforces传送门 生成函数好题. 卡场差评至今未过 题意简述:nnn个点的二叉树,每个点的权值KaTeX parse error: ...

  6. 【BZOJ3625】【codeforces438E】小朋友和二叉树 生成函数+多项式求逆+多项式开根

    首先,我们构造一个函数$G(x)$,若存在$k∈C$,则$[x^k]G(x)=1$. 不妨设$F(x)$为最终答案的生成函数,则$[x^n]F(x)$即为权值为$n$的神犇二叉树个数. 不难推导出,$ ...

  7. [Codeforces438E][bzoj3625] 小朋友和二叉树 [多项式求逆+多项式开根]

    题面 传送门 思路 首先,我们把这个输入的点的生成函数搞出来: $C=\sum_{i=0}^{lim}s_ix^i$ 其中$lim$为集合里面出现过的最大的数,$s_i$表示大小为$i$的数是否出现过 ...

  8. BZOJ 3625 [Codeforces Round #250]小朋友和二叉树 ——NTT 多项式求逆 多项式开根

    生成函数又有奇妙的性质. $F(x)=C(x)*F(x)*F(x)+1$ 然后大力解方程,得到一个带根号的式子. 多项式开根有解只与常数项有关. 发现两个解只有一个是成立的. 然后多项式开根.求逆. ...

  9. P6295-有标号 DAG 计数【多项式求逆,多项式ln】

    正题 题目链接:https://www.luogu.com.cn/problem/P6295 题目大意 求所有\(n\)个点的弱联通\(DAG\)数量. \(1\leq n\leq 10^5\) 解题 ...

  10. luogu P4725 多项式对数函数 (模板题、FFT、多项式求逆、求导和积分)

    手动博客搬家: 本文发表于20181125 13:25:03, 原地址https://blog.csdn.net/suncongbo/article/details/84487306 题目链接: ht ...

随机推荐

  1. 【51NOD-0】1049 最大子段和

    [算法]DP [题解]开long long…… #include<cstdio> #include<algorithm> #include<cstring> usi ...

  2. Linux while 和 read 的用法

    Reference: [ linux man doc ] [ CSDN roler_ ] [ Reads from the file descriptor] read 命令说明 SYNTAX : re ...

  3. Coursera在线学习---第九节(2).推荐系统

    一.基于内容的推荐系统(Content Based Recommendations) 所谓基于内容的推荐,就是知道待推荐产品的一些特征情况,将产品的这些特征作为特征变量构建模型来预测.比如,下面的电影 ...

  4. 配置连接的IP、端口、以及相应的数据库

    解压后里面有:lib 源文件 .examples 例子.test测试 将lib目录拷贝到你的项目中,就可以开始你的predis操作了. //使用autoload加载相关库,这边重点就是为了requir ...

  5. ERROR: do not initialise statics to false

    Question about git commit rule I git commit a patch, The patch has a "static int xxxxxxxxxxxxxx ...

  6. C#反射动态调用dll中的方法及使用QuartZ.net实现作业调度

    using Quartz; using Quartz.Impl; using System; using System.Collections.Generic; using System.Linq; ...

  7. 【bzoj4896】补退选

    傻逼题. 每个点维护下vector,然后随便做. #include<bits/stdc++.h> ; using namespace std; typedef long long ll; ...

  8. 使用XShell通过SSH访问Google谷歌云服务器方法

    1:先用Xshell创建个密钥 下一步到这里,这个名称要记得,谷歌后台要用的. 把这里的公钥复制出来,当然最好也可以备份下. 2:到谷歌后台去添加ssh,然后就能连接了. 复制刚才生成的公钥,在谷歌云 ...

  9. RadioButton 带下划线切换的案例

    xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout android:id=& ...

  10. tornado 响应头 中断 状态码 工作流程

    set_header    设置响应头 clear_header 清除响应头 add_header   增加响应头 self.flush  self.finish  中断 set_status     ...