题目

Source

http://www.tsinsen.com/A1493

Description

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

Input

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

Output

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

Sample Input

3
4
100000

Sample Output

4
38
829847355

分析

楼教主男人八题也又一题是和这题一样,n个有标号点能构成的简单无向连通图数,不过这题题目数据大很多。做法如下:

  • 补集转化,设$f[n]$表示n个带标号的点能构成的简单图数,而只要利用$f[n]$减去不连通的数目就是要求的答案了。其中$f[n]=2^{n(n-1)/2}$,因为完全图有$n(n-1)/2$条边,对于每条边选或不选来构成一张简单图。
  • $dp[n]$表示n个带标号的点能构成的简单无向连通图数
  • 考虑通过固定一个点,枚举这个点所在连通块的大小来转移:$dp[n]\ =\ f[n]-\sum_{i=1}^{n-1}C_{n-1}^{i-1}dp[i]f[n-i]$
  • 整理成卷积形式:$d[n]\ =\ f[n]-(n-1)!\sum_{i=1}^{n-1}((i-1)!)^{-1}d[i] \times ((n-i)!)^{-1}f[n-i]$
  • 最后就是用分治FFT来做了。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 262144 //const long long P=50000000001507329LL; // 190734863287 * 2 ^ 18 + 1
const int P=1004535809; // 479 * 2 ^ 21 + 1
//const int P=998244353; // 119 * 2 ^ 23 + 1
const int G=3; long long mul(long long x,long long y){
return x*y%P;
}
long long qpow(long long x,long long k){
long long ret=1;
while(k){
if(k&1) ret=mul(ret,x);
k>>=1;
x=mul(x,x);
}
return ret;
} long long wn[25];
void getwn(){
for(int i=1; i<=21; ++i){
int t=1<<i;
wn[i]=qpow(G,(P-1)/t);
}
} int len;
void NTT(long long y[],int op){
for(int i=1,j=len>>1,k; i<len-1; ++i){
if(i<j) swap(y[i],y[j]);
k=len>>1;
while(j>=k){
j-=k;
k>>=1;
}
if(j<k) j+=k;
}
int id=0;
for(int h=2; h<=len; h<<=1) {
++id;
for(int i=0; i<len; i+=h){
long long w=1;
for(int j=i; j<i+(h>>1); ++j){
long long u=y[j],t=mul(y[j+h/2],w);
y[j]=u+t;
if(y[j]>=P) y[j]-=P;
y[j+h/2]=u-t+P;
if(y[j+h/2]>=P) y[j+h/2]-=P;
w=mul(w,wn[id]);
}
}
}
if(op==-1){
for(int i=1; i<len/2; ++i) swap(y[i],y[len-i]);
long long inv=qpow(len,P-2);
for(int i=0; i<len; ++i) y[i]=mul(y[i],inv);
}
}
void Convolution(long long A[],long long B[],int n){
for(len=1; len<(n<<1); len<<=1);
for(int i=n; i<len; ++i){
A[i]=B[i]=0;
} NTT(A,1); NTT(B,1);
for(int i=0; i<len; ++i){
A[i]=mul(A[i],B[i]);
}
NTT(A,-1);
} long long A[MAXN],B[MAXN]; long long d[MAXN],f[MAXN]={1},fact[MAXN]={1},fact_inv[MAXN]={1};
/*
d[n] = f[n]-fact[n-1]*Σ(fact_inv[i-1]*d[i]*f[n-i]*fact_inv[n-i])
*/
void cdq(int l,int r){
if(l==r) return;
int mid=l+r>>1;
cdq(l,mid);
for(int i=l; i<=mid; ++i){
A[i-l]=mul(fact_inv[i-1],d[i]);
}
for(int i=mid-l+1; i<=r-l; ++i) A[i]=0;
for(int i=0; i<=r-l; ++i){
B[i]=mul(fact_inv[i],f[i]);
}
Convolution(A,B,r-l+1);
for(int i=mid+1; i<=r; ++i){
d[i]-=mul(fact[i-1],A[i-l]);
if(d[i]<0) d[i]+=P;
}
cdq(mid+1,r);
} int main(){
getwn();
for(int i=1; i<=130000; ++i){
fact[i]=mul(fact[i-1],i);
fact_inv[i]=qpow(fact[i],P-2);
d[i]=f[i]=qpow(2,(i-1LL)*i/2);
}
cdq(1,130000);
int n;
while(~scanf("%d",&n)){
printf("%lld\n",d[n]);
}
return 0;
}

Tsinsen A1493 城市规划(DP + CDQ分治 + NTT)的更多相关文章

  1. HDU5322 Hope(DP + CDQ分治 + NTT)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5322 Description Hope is a good thing, which can ...

  2. 【BZOJ-3456】城市规划 CDQ分治 + NTT

    题目链接 http://www.lydsy.com/JudgeOnline/problem.php?id=3456 Solution 这个问题可以考虑dp,利用补集思想 N个点的简单图总数量为$2^{ ...

  3. bzoj 2244 [SDOI2011]拦截导弹(DP+CDQ分治+BIT)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2244 [题意] 给定n个二元组,求出最长不上升子序列和各颗导弹被拦截的概率. [思路] ...

  4. 【bzoj3672】[Noi2014]购票 斜率优化dp+CDQ分治+树的点分治

    题目描述  给出一棵以1为根的带边权有根树,对于每个根节点以外的点$v$,如果它与其某个祖先$a$的距离$d$不超过$l_v$,则可以花费$p_vd+q_v$的代价从$v$到$a$.问从每个点到1花费 ...

  5. 斜率dp cdq 分治

    f[i] = min { f[j] + sqr(a[i] - a[j]) } f[i]= min { -2 * a[i] * a[j] + a[j] * a[j] + f[j] } + a[i] * ...

  6. BZOJ 2726: [SDOI2012]任务安排( dp + cdq分治 )

    考虑每批任务对后面任务都有贡献, dp(i) = min( dp(j) + F(i) * (T(i) - T(j) + S) ) (i < j <= N)  F, T均为后缀和. 与j有关 ...

  7. bzoj1492--斜率优化DP+cdq分治

    显然在某一天要么花完所有钱,要么不花钱. 所以首先想到O(n^2)DP: f[i]=max{f[i-1],(f[j]*r[j]*a[i]+f[j]*b[i])/(a[j]*r[j]+b[j])},j& ...

  8. bzoj 2726 [SDOI2012]任务安排(斜率DP+CDQ分治)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2726 [题意] 将n个任务划分成若干个块,每一组Mi任务花费代价(T+sigma{ t ...

  9. 斜率dp+cdq分治

    写在前面 这个东西应该是一个非常重要的套路......所以我觉得必须写点什么记录一下,免得自己忘掉了 一直以来我的斜率dp都掌握的不算很好......也很少主动地在比赛里想到 写这个的契机是noi.a ...

随机推荐

  1. Netty 实现 WebSocket 聊天功能

    上一次我们用Netty快速实现了一个 Java 聊天程序(见http://www.waylau.com/netty-chat/).现在,我们要做下修改,加入 WebSocket 的支持,使它可以在浏览 ...

  2. js的DOM的方法和属性总结

    1.DOM的获取元素document.getElementById()context.getElementsByTagName(tag) (可以获取相应上下文环境所有的tag标签)context.ge ...

  3. JavaScript 常用正则表达式

    ==========================正则表达式=========================== 常用元字符 代码 说明 . 匹配除换行符以外的任意字符 \w 匹配字母或数字或下划 ...

  4. vs里根据json快速创建对应类的方法

    有时候,我们在调用别人接口的时候,服务端返回了一个json格式的字符串,我们要获取json里面的数据的话一般有两种方式: 1.通过正则 2.反序列化成一个对象 第一种方式这里不再多说,主要说一下第二种 ...

  5. [2013-08-01]window.open

    经常上网的朋友可能会到过这样一些网站,一进入首页立刻会弹出一个窗口,或者按一个连接或按钮弹出,通常在这个窗口里会显示一些注意事项.版权信息.警告.欢迎光顾之类的话或者作者想要特别提示的信息.其实制作这 ...

  6. Json数组追加数据

    背景:在做一个购物车的时候,点击第一个商品,然后存入一个json数组中,点击第二个商品的时候,又继续在json数组中追加,代码如下: <script type="text/javasc ...

  7. 修改linux文件权限

    Linux系统中的每个文件和目录都有访问许可权限,用它来确定谁可以通过何种方式对文件和目录进行访问和操作. 文件或目录的访问权限分为只读,只写和可执行三种.以文件为例,只读权限表示只允许读其内容,而禁 ...

  8. 关于for循环------swift3.0

    在程序开发当中,for循环使用的频率无疑是最高的.常用的swift循环是递增式遍历.当然各种循环,swift都能办到.但其大多采用关键字形式实现,大部分开发者更喜欢直接使用C式循环代码.在swift3 ...

  9. 3dmax导出到blend或者vs中

    使用3dmax将模型导成obj格式的时候,可以导出材质或者不导出. 1.如果不导出,则按下图不勾选导出材质和创建材质库选项.这样生成的obj是可以直接再blend或者vs中打开的. 2.如果导出,不仅 ...

  10. SortedList和HashTable

    都是集合类,C#中同属命名空间System.Collections,“用于处理和表现类似keyvalue的键值对,其中key通常可用来快速查找,同时key是区分大小写:value用于存储对应于key的 ...