[bzoj3456]城市规划:多项式,分治

Description

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

物理学考是想FFT的好时间。

首先,按照习惯FFT的题先当成dp做。

设$f_i$表示有i个点的联通图有几个。

然后我们发现它不能转移。

于是我们设$g_i$表示有i个点的不联通图有几个。

$f_i+g_i=2^{\frac{i \times (i-1)}{2}}$

就是联不联通的情况都加起来就是所有的图,总数量就是讨论每一条边建不建。

然后我们要考虑怎么转移不会重复。一个比较简单的想法是去掉不联通图中的联通块,但是这样会重复。

多yy几分钟。于是就想到之前的常用技巧:钦定。

我们钦定编号最大的点所在的联通块。每次只去除这个联通块。这样就不重复了。

$g_i=\sum\limits_{j=1}^{i-1} f_j \times (f_{i-j} + g_{i-j}) \times C_{i-1}^{j-1}$

含义就是:枚举i号点所在的联通块大小为j,这个联通块的总方案数是$f_j$,剩余部分随意反正它已经不联通了,是$f_{i-j}+g_{i-j}$

然后再在除了i号点以外的$i-1$个点中选定具体是哪$j-1$个点和点i在同一个联通块里,是$C_{i-1}^{j-1}$

然后发现转移是带有依赖的,于是用分治FFT解决。

 1 #include<cstdio>
 2 #define int long long
 3 #define mod 1004535809
 4 #define S 131073
 5 int a[S],b[S],h[S],fac[S],inv[S],g[S],len,n,rev[S];
 6 int pow(int b,int t,int a=1){for(;t;t>>=1,b=b*b%mod)if(t&1)a=a*b%mod;return a;}
 7 int C(int b,int t){return fac[b]*inv[t]%mod*inv[b-t]%mod;}
 8 void NTT(int *a,int opt){
 9     for(int i=1;i<len;++i)rev[i]=rev[i>>1]>>1|(i&1?len>>1:0);
10     for(int i=0;i<len;++i)if(rev[i]>i)a[i]^=a[rev[i]]^=a[i]^=a[rev[i]];
11     for(int mid=1;mid<len;mid<<=1)
12         for(int i=0,t=pow(3,opt*(mod-1)/mid/2+mod-1);i<len;i+=mid<<1)
13             for(int j=0,w=1,x,y;j<mid;++j,w=w*t%mod)
14                 x=a[i+j],y=a[i+j+mid]*w%mod,a[i+j]=(x+y)%mod,a[i+j+mid]=(x-y+mod)%mod;
15     if(opt==-1)for(int i=0,iv=pow(len,mod-2);i<len;++i)a[i]=a[i]*iv%mod;
16 }
17 void solve(int l,int r){
18     if(l==r){g[l]=fac[l-1]*g[l]%mod;return;}
19     int mid=l+r>>1;solve(l,mid);
20     len=1;while(len<=r-l+1)len<<=1;
21     for(int i=0;i<len;++i)a[i]=b[i]=0;
22     for(int i=0;i<=r-l+1;++i)a[i]=h[i]*inv[i]%mod;
23     for(int i=l;i<=mid;++i)b[i-l]=(h[i]-g[i]+mod)*inv[i-1]%mod;
24     NTT(a,1);NTT(b,1);
25     for(int i=0;i<len;++i)a[i]=a[i]*b[i]%mod;
26     NTT(a,-1);
27     for(int i=mid+1;i<=r;++i)g[i]=(g[i]+a[i-l])%mod;
28     solve(mid+1,r);
29 }
30 signed main(){
31     scanf("%lld",&n);fac[0]=1;
32     for(int i=1;i<=n;++i)fac[i]=fac[i-1]*i%mod;
33     inv[n]=pow(fac[n],mod-2);
34     for(int i=n-1;~i;--i)inv[i]=inv[i+1]*(i+1)%mod;
35     for(int i=1;i<=n;++i)h[i]=pow(2,i*(i-1)/2);
36     solve(1,n);printf("%lld\n",(h[n]-g[n]+mod)%mod);
37 }

原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/12012535.html

时间: 2024-10-08 01:16:30

[bzoj3456]城市规划:多项式,分治的相关文章

BZOJ3456 城市规划 【分治NTT】

题目链接 BZOJ3456 题解 据说这题是多项式求逆 我太弱不会QAQ,只能\(O(nlog^2n)\)分治\(NTT\) 设\(f[i]\)表示\(i\)个节点的简单无向连通图的数量 考虑转移,直接求不好求,我们知道\(n\)个点无向图的数量是\(2^{{n \choose 2}}\)的,考虑用总数减去不连通的 既然图不连通,那么和\(1\)号点联通的点数一定小于\(n\),我们枚举和\(1\)号点所在联通块大小,就可以得到式子: \[f[n] = 2^{{n \choose 2}} - \

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

城市规划 时间限制:40s      空间限制:256MB 题目描述 刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了.  刚才说过, 阿狸的国家有n个城市, 现在国家需要在某些城市对之间建立一些贸易路线, 使得整个国家的任意两个城市都直接或间接的连通. 为了省钱, 每两个城市之间最多只能有一条直接的贸易路径. 对于两个建立路线的方案, 如果存在一个城市对, 在两个方案中是否建立路线不一样, 那么这两个方案就是不同的, 否则就是相同的. 现在你需要求出一共有多少不同的方案.  好了, 这就

[bzoj3456]城市规划——分治FFT

题目大意: 求n个点的带标号简单无向联通图的数目. 思路: 嗯多项式求逆还不会,到时候会了应该会补吧. 这种和图计数有关的题目一般都是考虑反面计数或者是容斥什么的. 考虑枚举一号点的连通块的大小,然后用总方案数减去这些方案数. 可以得到递推式: \[ f_{i}=2^{i\choose 2}-\sum_{j=1}^{i-1}{i-1\choose j-1}\times f_{j}\times 2^{i-j\choose2} \] 后面的式子可以化为卷积的形式: \[ f_{i}=2^{i\cho

bzoj3456 城市规划

Description 求含有n个点有标号的无向联通图的个数(没有重边),n<=130000 Input 3 Output 4 正解:$分治FFT$/多项式求逆. 并没有权限号,但是某$oj$里有这道题.. 我们考虑递推,$f[i]$表示$i$个点的联通图个数,那么用总数减去不合法的数量. 考虑枚举$1$号点所在的联通块的点数,那么我们可以得到: $f[n]=2^{\binom{n}{2}}-\sum_{i=1}^{n-1}f[i]*\binom{n-1}{i-1}*2^{\binom{n-i}

城市规划[多项式、连通图计数]

求出n个点的简单(无重边无自环)无向连通图数目,$n <= 130000$,$mod 1004535809$ 设$f_i$表示i个点的无向连通图数,连通图计数的套路,枚举1号点所在的连通块大小 \begin{array}{rcl}f_n&=&2^{C_n^2}-\sum\limits_{i=1}^{n-1}\binom{n-1}{i-1}f_i 2^{C_{n-i}^2}\\f_n&=&2^{C_n^2}-(n-1)!\sum\limits_{i=1}^{n-1}\f

BZOJ 3456 城市规划 多项式求ln

题意:链接 方法:多项式求ln 解析: 毒瘤题的倒数第二个- -! md毒瘤题都做完后再回来写题解真是爽歪歪 先看这道题怎么做. 首先一个简单无向图的边的个数是C(n,2),然后那么我们的选择就有2C(n,2)种. 然后我们再考虑简单无向连通图的方案数为fi. f[i]=2C(i,2)?∑i?1j=1f[j]?C(i?1,j?1)?2C(i?j,2) 上面的式子其实没啥卵用- 现在我们这么来考虑. 看如上大爷给出的PPT. 其实这个正体现了划分和被划分的关系. 对于简单无向图来说,简单无向连通图

BZOJ3456城市规划

BZOJ3456 http://www.lydsy.com/JudgeOnline/problem.php?id=3456 #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> using namespace std; const int mod=1004535809,maxn=1<<18|1; int p[maxn],gn[233]; int n; in

BZOJ3456:城市规划——题解

https://www.lydsy.com/JudgeOnline/problem.php?id=3456 求出n个点的简单(无重边无自环)无向连通图数目 模数很熟悉,先敲一个MTT. 然后通过推导式子就做完啦! 我觉得就算怎么讲也没有下面这一位好:http://blog.miskcoo.com/2015/05/bzoj-3456 另外多项式求逆:http://blog.miskcoo.com/2015/05/polynomial-inverse 至少我学到了:当你有个卷积知道答案,求卷积的一项

模板记录

NTT: namespace NTT { int n,m,l,r[N]; void NTT(int *a,int f) { for(int i=0;i<n;i++) if(i<r[i]) swap(a[i],a[r[i]]); for(int i=1;i<n;i<<=1) { int wn=q_pow(pr,phi/(i<<1)); if(f==-1) wn=q_pow(wn,mod-2); for(int p=i<<1,j=0;j<n;j+=p