[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}$下求多项式的逆元即可。
次数界放宽!递归求逆元的时候次数界要放成两倍!
#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)的更多相关文章
- FFT模板 生成函数 原根 多项式求逆 多项式开根
FFT #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> ...
- NTT+多项式求逆+多项式开方(BZOJ3625)
定义多项式$h(x)$的每一项系数$h_i$,为i在c[1]~c[n]中的出现次数. 定义多项式$f(x)$的每一项系数$f_i$,为权值为i的方案数. 通过简单的分析我们可以发现:$f(x)=\fr ...
- 【BZOJ3456】轩辕朗的城市规划 无向连通图计数 CDQ分治 FFT 多项式求逆 多项式ln
题解 分治FFT 设\(f_i\)为\(i\)个点组成的无向图个数,\(g_i\)为\(i\)个点组成的无向连通图个数 经过简单的推导(枚举\(1\)所在的连通块大小),有: \[ f_i=2^{\f ...
- bzoj 3456 城市规划——分治FFT / 多项式求逆 / 多项式求ln
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3456 分治FFT: 设 dp[ i ] 表示 i 个点时连通的方案数. 考虑算补集:连通的方 ...
- 2019.01.01 bzoj3625:小朋友和二叉树(生成函数+多项式求逆+多项式开方)
传送门 codeforces传送门codeforces传送门codeforces传送门 生成函数好题. 卡场差评至今未过 题意简述:nnn个点的二叉树,每个点的权值KaTeX parse error: ...
- 【BZOJ3625】【codeforces438E】小朋友和二叉树 生成函数+多项式求逆+多项式开根
首先,我们构造一个函数$G(x)$,若存在$k∈C$,则$[x^k]G(x)=1$. 不妨设$F(x)$为最终答案的生成函数,则$[x^n]F(x)$即为权值为$n$的神犇二叉树个数. 不难推导出,$ ...
- [Codeforces438E][bzoj3625] 小朋友和二叉树 [多项式求逆+多项式开根]
题面 传送门 思路 首先,我们把这个输入的点的生成函数搞出来: $C=\sum_{i=0}^{lim}s_ix^i$ 其中$lim$为集合里面出现过的最大的数,$s_i$表示大小为$i$的数是否出现过 ...
- BZOJ 3625 [Codeforces Round #250]小朋友和二叉树 ——NTT 多项式求逆 多项式开根
生成函数又有奇妙的性质. $F(x)=C(x)*F(x)*F(x)+1$ 然后大力解方程,得到一个带根号的式子. 多项式开根有解只与常数项有关. 发现两个解只有一个是成立的. 然后多项式开根.求逆. ...
- P6295-有标号 DAG 计数【多项式求逆,多项式ln】
正题 题目链接:https://www.luogu.com.cn/problem/P6295 题目大意 求所有\(n\)个点的弱联通\(DAG\)数量. \(1\leq n\leq 10^5\) 解题 ...
- luogu P4725 多项式对数函数 (模板题、FFT、多项式求逆、求导和积分)
手动博客搬家: 本文发表于20181125 13:25:03, 原地址https://blog.csdn.net/suncongbo/article/details/84487306 题目链接: ht ...
随机推荐
- bzoj 1006 MCS算法
根据陈丹琪的论文弦图与区间图,求出弦图的完美消除序列之后,反向给每个点染可以染的最小的颜色,这样可以使用最少的颜色染色,染色的方案即为队伍数. 那么我们需要求该图的完美消除序列,使用MCS算法,从后向 ...
- Kendo Grid:将Edit button 移到grid view 得顶部
因为kendo grid 得toolbar 里不包括Edit button,所以我们要先用template 创建一个自定义得edit button,然后再对这个button实现edit 功能. < ...
- typeof的用法
typeof可以返回变量的类型,返回值为字符串,其值有 "undefined" "boolean" "string" "numbe ...
- mysql中的enum型
enum设置后 值只能是给出的值中的其中一个 mysql> create table enum(e enum('1','2','3','4','5','6','7','8','9','10')) ...
- perl 在win下输出中文乱码问题
use utf8; my $name = '你好'; binmode(STDOUT, ":encoding(gbk)"); print $name,"\n"; ...
- bind类成员函数
首先描述一个情景: 先贴出代码: class Solution { public: bool compare(int a, int b) { return a > b; } int functi ...
- C++之指针,引用与数组
引用只是对象的另一个名字,通过在变量名前面添加"&”符号来定义,而指针保存的是另一个对象的地址,它们两都提供了间接访问所服务变量的途径. 但是它们的差别还是挺大的: 先从它们的值说起 ...
- perl操作MongoDB
perl操作MongoDB http://blog.csdn.net/jophyyao/article/details/8223190 Mongodb 的C语言操作 http://blog.csdn. ...
- yml格式
是什么? yml文件扩展名是YAML的缩写,YAML于2001年出现,是一种数据描述语言,和xml类似 为什么用它? 我们在做javaweb项目的时候最常见的就是.xml配置文件和properitie ...
- elasticsearch索引加别名
curl -XPOST 'http://localhost:9200/_aliases' -d ' { "actions": [ {&qu ...