[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\n",1ll*c[n]*fac[n-1]%mod);
59     return 0;
60 }

原文地址:https://www.cnblogs.com/HocRiser/p/8687578.html

时间: 2024-11-08 19:15:57

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

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

定义多项式h(x)的每一项系数hi,为i在c[1]~c[n]中的出现次数. 定义多项式f(x)的每一项系数fi,为权值为i的方案数. 通过简单的分析我们可以发现:f(x)=2/(sqrt(1-4h(x))+1) 于是我们需要多项式开方和多项式求逆. 多项式求逆: 求B(x),使得A(x)*B(x)=1 (mod x^m) 考虑倍增. 假设我们已知A(x)*B(x)=1 (mod x^m),要求C(x),使得A(x)*C(x)=1 (mod x^(2m)) 简单分析可得C(x)=B(x)*(2-A

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

题面 传送门 思路 首先,我们把这个输入的点的生成函数搞出来: \(C=\sum_{i=0}^{lim}s_ix^i\) 其中\(lim\)为集合里面出现过的最大的数,\(s_i\)表示大小为\(i\)的数是否出现过 我们再设另外一个函数\(F\),定义\(F_k\)表示总权值为\(k\)的二叉树个数 那么,一个二叉树显然可以通过两个子树(可以权值为0,也就是空子树)和一个节点构成 那么有如下求\(F\)的式子 \(F_0=1\) \(F_k=\sum_{i=0}^k s_i \sum_{j=0

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

手动博客搬家: 本文发表于20181125 13:25:03, 原地址https://blog.csdn.net/suncongbo/article/details/84487306 题目链接: https://www.luogu.org/problemnew/show/P4725 题目大意: 给定一个\(n\)次多项式\(A(x)\), 求一个\(n\)次多项式\(B(x)\)满足\(B(x)\equiv \ln A(x) (\mod x^n)\) 题解: 神数学模板题-- 数学真奇妙! 前驱

luoguP4512 【模板】多项式除法 NTT+多项式求逆+多项式除法

Code: #include<bits/stdc++.h> #define maxn 300000 #define ll long long #define MOD 998244353 #define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout) using namespace std; namespace poly{ #define

BZOJ 3625 多项式求逆+多项式开根

思路: RT //By SiriusRen #include <bits/stdc++.h> using namespace std; const int N=1<<18,mod=998244353; int A[N],C[N],invC[N],c[N],d[N],R[N],tmp[N],xx,len,sqrA[N],F[N]; typedef long long ll; int power(ll x,int y){ ll res=1; while(y){ if(y&1)r

【bzoj3456】城市规划(多项式求逆+dp)

Description 求\(~n~\)个点组成的有标号无向连通图的个数.\(~1 \leq n \leq 13 \times 10 ^ 4~\). Solution 这道题的弱化版是poj1737, 其中\(n \leq 50\), 先来解决这个弱化版的题.考虑\(~dp~\),直接统计答案难以入手,于是考虑容斥.显然有,符合条件的方案数\(=\)所有方案数\(-\)不符合条件的方案数,而这个不符合条件的方案数就是图没有完全联通的情况.设\(~dp_i~\)表示\(~i~\)个点组成的合法方案

【bzoj3456】城市规划 容斥原理+NTT+多项式求逆

题目描述 求出n个点的简单(无重边无自环)无向连通图数目mod 1004535809(479 * 2 ^ 21 + 1). 输入 仅一行一个整数n(<=130000) 输出 仅一行一个整数, 为方案数 mod 1004535809. 样例输入 3 样例输出 4 题解 容斥原理+NTT+多项式求逆 设 $f_i$ 表示 $i$ 个点的简单无向连通图的数目,$g_i$ 表示 $i$ 个点的简单无向图的数目. 根据定义得 $g_i=2^{\frac{n(n-1}2}$ . 对于 $f_i$ ,考虑容斥

【BZOJ 3456】 3456: 城市规划 (NTT+多项式求逆)

3456: 城市规划 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 658  Solved: 364 Description 刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了. 刚才说过, 阿狸的国家有n个城市, 现在国家需要在某些城市对之间建立一些贸易路线, 使得整个国家的任意两个城市都直接或间接的连通. 为了省钱, 每两个城市之间最多只能有一条直接的贸易路径. 对于两个建立路线的方案, 如果存在一个城市对, 在两个方案中是否建立路线不一

CF438E The Child and Binary Tree(生成函数+多项式开根+多项式求逆)

传送门 可以……这很多项式开根模板……而且也完全不知道大佬们怎么把这题的式子推出来的…… 首先,这题需要多项式开根和多项式求逆.多项式求逆看这里->这里,这里讲一讲多项式开根 多项式开方:已知多项式$A$,求多项式$B$满足$A^2\equiv B\pmod{x^n}$(和多项式求逆一样这里需要取模,否则$A$可能会有无数项) 假设我们已经求出$A'^2\equiv B\pmod{x^n}$,考虑如何计算出$A^2\equiv B\pmod{x^{2n}}$ 首先肯定存在$A^2\equiv B