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解决。

 #include<cstdio>
#define int long long
#define mod 1004535809
#define S 131073
int a[S],b[S],h[S],fac[S],inv[S],g[S],len,n,rev[S];
int pow(int b,int t,int a=){for(;t;t>>=,b=b*b%mod)if(t&)a=a*b%mod;return a;}
int C(int b,int t){return fac[b]*inv[t]%mod*inv[b-t]%mod;}
void NTT(int *a,int opt){
for(int i=;i<len;++i)rev[i]=rev[i>>]>>|(i&?len>>:);
for(int i=;i<len;++i)if(rev[i]>i)a[i]^=a[rev[i]]^=a[i]^=a[rev[i]];
for(int mid=;mid<len;mid<<=)
for(int i=,t=pow(,opt*(mod-)/mid/+mod-);i<len;i+=mid<<)
for(int j=,w=,x,y;j<mid;++j,w=w*t%mod)
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;
if(opt==-)for(int i=,iv=pow(len,mod-);i<len;++i)a[i]=a[i]*iv%mod;
}
void solve(int l,int r){
if(l==r){g[l]=fac[l-]*g[l]%mod;return;}
int mid=l+r>>;solve(l,mid);
len=;while(len<=r-l+)len<<=;
for(int i=;i<len;++i)a[i]=b[i]=;
for(int i=;i<=r-l+;++i)a[i]=h[i]*inv[i]%mod;
for(int i=l;i<=mid;++i)b[i-l]=(h[i]-g[i]+mod)*inv[i-]%mod;
NTT(a,);NTT(b,);
for(int i=;i<len;++i)a[i]=a[i]*b[i]%mod;
NTT(a,-);
for(int i=mid+;i<=r;++i)g[i]=(g[i]+a[i-l])%mod;
solve(mid+,r);
}
signed main(){
scanf("%lld",&n);fac[]=;
for(int i=;i<=n;++i)fac[i]=fac[i-]*i%mod;
inv[n]=pow(fac[n],mod-);
for(int i=n-;~i;--i)inv[i]=inv[i+]*(i+)%mod;
for(int i=;i<=n;++i)h[i]=pow(,i*(i-)/);
solve(,n);printf("%lld\n",(h[n]-g[n]+mod)%mod);
}

最新文章

  1. airflow 部署
  2. 再看Ajax
  3. (转)JavaScript中的运算符优先级
  4. ArcGIS for Flex中引入google map作底图
  5. Centos7开启防火墙并且使MYSQL外网访问开放3306端口
  6. C# 支持多种语言
  7. cefSharp在XP下使得程序崩溃记录
  8. java下实现调用oracle的存储过程和函数
  9. 3.4 spring- lookup-method 子元素的使用与解析
  10. 积和式Permanent在Mathematica中的运算
  11. javascript 写职责链
  12. Checbox的操作含已选、未选及判断代码
  13. 测测你适合从事Web前端开发吗
  14. PHP导出Excel 数字末尾变0或小数点解决办法
  15. Java框架之Hibernate(二)
  16. JavaEE GenericServlet 解析
  17. Hibernate(十一):映射继承关系的三种方案
  18. 细谈getRequestDispatcher()与sendRedirect()的区别
  19. memcache、redis、mongoDB 如何选择?
  20. tesseract-ocr识别中文扫描图片实例讲解

热门文章

  1. 【关注图像采集视频传输】之 Cy3014 usb3.0 FIFO接口
  2. Python3 模块基础
  3. python之with语句结合上下文管理器
  4. 【Java Web开发学习】Spring MVC 开始配置
  5. 【设计模式】代理模式-Proxy
  6. Oracle数据库备份/导出(exp/expd)、导入(imp/impd)
  7. django基础之day09,Forms组件在程序中做了哪些事? 校验数据、渲染标签、展示信息
  8. spring boot 2 全局统一返回RESTful风格数据、统一异常处理
  9. js获取当前时间的年月日时分秒以及时间的格式化
  10. mysql安装过程及无法启动mysql的办法