试题来源
  2013中国国家集训队第二次作业
问题描述
  刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了.
  刚才说过, 阿狸的国家有n个城市, 现在国家需要在某些城市对之间建立一些贸易路线, 使得整个国家的任意两个城市都直接或间接的连通.
  为了省钱, 每两个城市之间最多只能有一条直接的贸易路径. 对于两个建立路线的方案, 如果存在一个城市对, 在两个方案中是否建立路线不一样, 那么这两个方案就是不同的, 否则就是相同的. 现在你需要求出一共有多少不同的方案.
  好了, 这就是困扰阿狸的问题. 换句话说, 你需要求出n个点的简单(无重边无自环)无向连通图数目.
  由于这个数字可能非常大, 你只需要输出方案数mod 1004535809(479 * 2 ^ 21 + 1)即可.
输入格式
  仅一行一个整数n(<=130000)
输出格式
  仅一行一个整数, 为方案数 mod 1004535809.
样例输入
3
样例输出
4
样例输入
4
样例输出
28
样例输入
100000
样例输出
829847355
数据规模和约定
  对于 20%的数据, n <= 10
  对于 40%的数据, n <= 1000
  对于 60%的数据, n <= 30000
  对于 80%的数据, n <= 60000
  对于 100%的数据, n <= 130000
【分析】
非常巧妙的题目。
首先可以推递推式,用f(n) = 2^C(n,2) - sigma{(2 ^ C(n - i, 2)) * C(n - 1, i - 1) * f(i) |  1<= i <n  }
相当于选定一个点不动,逐步扩大该点所在的联通快的大小。
可以保证不会出现重复。
经过化简将C(n-1,i-1)中的(n-1)!提出来以后,可以通过一种非常巧妙的构造卷积的方式解决问题(详见代码)。
为什么可以用FFT?。。。。FFT怎么取模啊,不会QAQ。
 /*
宋代朱敦儒
《西江月·世事短如春梦》
世事短如春梦,人情薄似秋云。不须计较苦劳心。万事原来有命。
幸遇三杯酒好,况逢一朵花新。片时欢笑且相亲。明日阴晴未定。
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <iostream>
#include <string>
#include <ctime>
#define LOCAL
const int MAXN = * * + ;
const long long MOD = ;//费马数论变换的费马素数
long long G = ;//元根
using namespace std;
typedef long long ll;
ll x1[MAXN], x2[MAXN];
ll data[MAXN], Ans[MAXN];
ll f[MAXN], I[MAXN], nI[MAXN], C[MAXN];
ll inv2[MAXN], wn[MAXN], Inv[MAXN]; ll pow(ll a, ll b){
if (b == ) return % MOD;
if (b == ) return a % MOD;
ll tmp = pow(a, b / );
if (b % == ) return (tmp * tmp) % MOD;
else return ((tmp * tmp) % MOD * (a % MOD)) % MOD;
}
ll exgcd(ll a, ll b, ll &x, ll &y){
if (b == ){x = 1ll; y = ; return a;}
ll tmp = exgcd(b, a % b, y, x);
y -= x * (a / b);
return tmp;
}
ll inv(ll a, ll p){
ll x, y;
ll tmp = exgcd(a, p, x, y);
return ((x % MOD) + MOD) % MOD;
}
void change(ll *x, int len, int loglen){
for (int i = ; i < len; i++){
int t = i, k = , tmp = loglen;
while (tmp--) {k = (k << ) + (t & ); t >>= ;}
if (k < i) swap(x[i], x[k]);
}
return;
}
void FNT(ll *x, int len, int loglen, int type){
if (type) change(x, len, loglen);
int t;
t = (type ? : ( << loglen));
for (int i = ; i < loglen; i++){
if (!type) t >>= ;
int l = , r = l + t;
while (l < len){
ll a, b;
ll tmp = 1ll, w = wn[t];
if (!type) w = Inv[t];
for (int j = l; j < l + t; j++){
if (type){
a = x[j] % MOD;
b = (x[j + t] * (tmp % MOD)) % MOD;
x[j] = (a + b) % MOD;
x[j + t] = ((a - b) % MOD + MOD) % MOD;
}else{
a = (x[j] + x[j + t]) % MOD;
b = ((((x[j] - x[j + t]) % MOD + MOD) % MOD) * tmp) % MOD;
x[j] = a;
x[j + t] = b;
}
tmp = (tmp * w) % MOD;
}
l = r + t;
r = l + t;
}
if (type) t <<= ;
}
if (!type){
change(x, len, loglen);
for (int i = ; i < len; i++) x[i] = (x[i] % MOD * inv(len, MOD)) % MOD;
}
}
//CDQ分治
void solve(int l, int r){
if (l == r){
//T为组合数的, I[l]为阶乘的模
f[l] = (C[l] - (I[l - ] * f[l]) % MOD + MOD) % MOD;
return;
}
int mid = (l + r) >> ;
solve(l, mid);
int len = max(mid - l + , r - mid), loglen = ;
while ((<<loglen) < ((r - l + ) << )) loglen++;//要把卷积分成两个部分 for (int i = ; i < (<<loglen); i++) x1[i] = x2[i] = ;
for (int i = l; i <= mid; i++) x1[i - l] = (nI[i - ] * f[i]) % MOD;
for (int i = ; i <= r - l; i++) x2[i] = (C[i] * nI[i]) % MOD; FNT(x1, (<<loglen), loglen, );
FNT(x2, (<<loglen), loglen, );
for (int i = ; i < (<<loglen); i++) x1[i] = (x1[i] * x2[i]) % MOD;
FNT(x1, (<<loglen), loglen, );
for (int i = mid + ; i <= r; i++) f[i] = (f[i] + x1[i - l] % MOD) % MOD;
solve(mid + , r);
}
int n;
void init(){
scanf("%d", &n);
inv2[] = ;
inv2[] = inv(, MOD);
//预处理2的阶乘的逆元
for (int i = ; i <= n; i++) inv2[i] = (inv2[i - ] * inv2[]) % MOD;
for (int i = ; i <= * n; i++){
if (i != && (MOD - ) / ( * i) == (MOD - ) / ( * (i - ))){
wn[i] = wn[i - ];
Inv[i] = Inv[i - ];
}else{
wn[i] = pow(G, (MOD - ) / ( * i)) % MOD;
Inv[i] = inv(wn[i], MOD) % MOD;
}
}
I[] = nI[] = ;//分别代表阶乘和阶乘的-1次方
for (int i = ; i <= n; i++){
I[i] = (long long)(i * I[i - ]) % MOD;
nI[i] = (inv((long long)i, MOD) * nI[i - ]) % MOD;
//printf("%lld\n", nI[i]);
}
//预处理组合数2^C(n, 2)
for (int i = ; i <= n; i++){
C[i] = pow(2ll, (long long)((long long)i * (i - )) / ) % MOD;
//printf("%lld\n", C[i]);
}
} int main() { init();
solve(, n);
printf("%lld\n", f[n]);
return ;
}

【BZOJ3456】【CDQ分治+FNT】城市规划的更多相关文章

  1. 【BZOJ3456】轩辕朗的城市规划 无向连通图计数 CDQ分治 FFT 多项式求逆 多项式ln

    题解 分治FFT 设\(f_i\)为\(i\)个点组成的无向图个数,\(g_i\)为\(i\)个点组成的无向连通图个数 经过简单的推导(枚举\(1\)所在的连通块大小),有: \[ f_i=2^{\f ...

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

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

  3. [BZOJ 3456]城市规划(cdq分治+FFT)

    [BZOJ 3456]城市规划(cdq分治+FFT) 题面 求有标号n个点无向连通图数目. 分析 设\(f(i)\)表示\(i\)个点组成的无向连通图数量,\(g(i)\)表示\(i\)个点的图的数量 ...

  4. 【教程】简易CDQ分治教程&学习笔记

    前言 辣鸡蒟蒻__stdcall终于会CDQ分治啦!       CDQ分治是我们处理各类问题的重要武器.它的优势在于可以顶替复杂的高级数据结构,而且常数比较小:缺点在于必须离线操作. CDQ分治的基 ...

  5. BZOJ 2683 简单题 ——CDQ分治

    [题目分析] 感觉CDQ分治和整体二分有着很本质的区别. 为什么还有许多人把他们放在一起,也许是因为代码很像吧. CDQ分治最重要的是加入了时间对答案的影响,x,y,t三个条件. 排序解决了x ,分治 ...

  6. HDU5618 & CDQ分治

    Description: 三维数点 Solution: 第一道cdq分治...感觉还是很显然的虽然题目不能再傻逼了... Code: /*=============================== ...

  7. 初识CDQ分治

    [BZOJ 1176:单点修改,查询子矩阵和]: 1176: [Balkan2007]Mokia Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 200 ...

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

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

  9. BZOJ4170 极光(CDQ分治 或 树套树)

    传送门 BZOJ上的题目没有题面-- [样例输入] 3 5 2 4 3 Query 2 2 Modify 1 3 Query 2 2 Modify 1 2 Query 1 1 [样例输出] 2 3 3 ...

随机推荐

  1. MVC Model 数据注解与验证

    常用验证特性: using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Sch ...

  2. DevExpress的JavaScript脚本智能提示

    http://www.cnblogs.com/zhaozhan/archive/2011/06/08/2075767.html ASPxScriptIntelliSense.js在安装目录下的Comp ...

  3. wxWidgets一个界面与数据分离的简单例子

    /*************************************************************** * Name: MyApp.h * Purpose: Defines ...

  4. Windows和Ubuntu双系统,修复UEFI引导的两种办法

    查看ubuntu是否是从 efi/uefi 启动的方法:  若 /sys/firmware/efi 存在则是,否则不是.shell命令: [ -d /sys/firmware/efi ] && ...

  5. 在Jersey中如何处理泛型集合

    Jersey是一个标准的Restful Web service框架,可以方便的实现Restful的Server端和客户端. 本文主要介绍使用Jersey客户端时如何将Json格式的数组转换成java的 ...

  6. Cocos2d-js 3.0 alp2 使用指南

    Download Cocos2d-JS: http://www.cocos2d-x.org/download Unzip and copy to C:/ Download JDK: http://ww ...

  7. PowerMock注解PowerMockIgnore的使用方法

    故事要从一个异常开始,某天我在开发一个加密.解密特性,算法使用的是3DES,样例代码如下. package org.jackie.study.powermock; import java.io.Uns ...

  8. malloc()与calloc差别

    Both the malloc() and the calloc() functions are used to allocate dynamic memory. Each operates slig ...

  9. Android自定义“图片+文字”控件四种实现方法之 二--------个人最推荐的一种

    http://blog.csdn.net/yanzi1225627/article/details/8633872 第二种方法也要新建一个图片+文字的xml布局文件,然后写一个类继承自LinearLa ...

  10. FASTDFS 5X安装

    FASTDFS 5X安装 http://www.wingdevops.com/?p=603 流行的开源分布式文件系统有很多,FastDFS 是国人在mogileFS的基础上进行改进的key-value ...