题目链接:

http://poj.org/problem?id=1737

题意:

求 \(n\) 个点的无向简单(无重边无自环)连通图的个数。\((n<=50)\)

题解:

这题你甚至能OEIS。

http://oeis.org/A001187

但不支持这样做。TAT

间接做。

总方案数减去不合法方案。

因为\(n\)个点的完全图有 \(C(n,2)={n(n-1) \over 2}\) 条边,显然就有 \(2^{C(n,2)}\) 种子图,即枚举每条边是否选择。

设$ f[i]$ 表示每个点都和点 \(1\) 相连的连通图的个数 。

假设\(1\) 号点所在的连通块大小为 \(i\)。那么和 \(1\) 连通的这 \(i−1\) 个点就有 \(C(n-1,i-1)\) ,方案数则为:\(C(n-1,i-1)*f[i]\)。

然后其它 \(n−i\) 个点间任意连边即可,这时方案数为 \(2^{C(n-i,2)}\)。

综上,则存在递推式:

$$f[n]=2{C(n,2)}-\sum_{i=1}{n-1}f[i]C(n-1,i-1)2^{C(n-i,2)}$$

答案就是\(f[n]\)。

然后就套个大数板子。额...过世OJ好像不支持c++11。懒得改了,虽然不过,但代码是正确的。QAQ

代码:

#include <iostream>
#include <vector>
#include <cmath>
#include <complex>
#include <cstring>
#include <stdlib.h>
#include <string.h>
using namespace std;
typedef long long LL;
const double PI = acos(-1);
void rader(vector<complex<double> >& y) {
int len = y.size();
int i, j, k;
for (i = 1, j = len / 2; i < len - 1; i++) {
if (i < j) swap(y[i], y[j]);
k = len / 2;
while (j >= k) {
j -= k;
k /= 2;
}
if (j < k) j += k;
}
}
void fft(vector<complex<double> >& y, int on) {
int len = y.size();
rader(y);
for (int h = 2; h <= len; h <<= 1) {
complex<double> wn(cos(-on * 2 * PI / h), sin(-on * 2 * PI / h));
for (int j = 0; j < len; j += h) {
complex<double> w(1, 0);
for (int k = j; k < j + h / 2; k++) {
complex<double> u = y[k];
complex<double> t = w * y[k + h / 2];
y[k] = u + t;
y[k + h / 2] = u - t;
w = w * wn;
}
}
}
if (on == -1) for (auto& i : y) i.real(i.real() / len);
}
class BigInt {
private:
string num;
string sign; public:
const string to_string() const {
if (this->sign == "-") return this->sign + this->num;
else return this->num;
}
const LL toll() { return stoll(this->to_string()); }
const int toi() { return stoi(this->to_string()); }
BigInt() : num("0"), sign("+") {}
BigInt(const int t) {
if (t < 0) {
this->num = std::to_string(-t);
this->sign = "-";
} else {
this->num = std::to_string(t);
this->sign = "+";
}
}
BigInt(const LL t) {
if (t < 0) {
this->num = std::to_string(-t);
this->sign = "-";
} else {
this->num = std::to_string(t);
this->sign = "+";
}
}
BigInt(const string& t) {
if (t[0] == '-') {
this->num = t.substr(1);
this->sign = "-";
} else {
this->num = t;
this->sign = "+";
}
int flag = 0;
while (flag < (int)this->num.length() - 1 && this->num[flag] == '0') flag++;
this->num = this->num.substr(flag);
}
BigInt(char* const t) : BigInt(string(t)) {}
friend bool operator< (const BigInt& t, const BigInt& s) {
if (t.sign != s.sign) {
if (t.sign == "-") return true;
else return false;
} else {
if (t.sign == "-") {
if (t.num.length() == s.num.length()) {
return t.num > s.num;
} else {
return t.num.length() > s.num.length();
}
} else {
if (t.num.length() == s.num.length()) {
return t.num < s.num;
} else {
return t.num.length() < s.num.length();
}
}
}
}
friend bool operator> (const BigInt& t, const BigInt& s) {
return s < t;
}
friend bool operator== (const BigInt& t, const BigInt& s) {
return t.num == s.num && t.sign == s.sign;
}
friend bool operator!= (const BigInt& t, const BigInt& s) {
return !(t == s);
}
friend bool operator<= (const BigInt& t, const BigInt& s) {
return t == s || t < s;
}
friend bool operator>= (const BigInt& t, const BigInt& s) {
return t == s || t > s;
}
friend const BigInt abs(const BigInt& t) {
BigInt ans = t;
if (ans.sign == "-") ans.sign = "+";
return ans;
}
friend const BigInt operator- (const BigInt& t) {
BigInt ans = t;
if (ans.sign == "-") ans.sign = "+";
else ans.sign = "-";
return ans;
}
friend istream& operator>> (istream& in, BigInt& t) {
string s;
in >> s;
t = s;
return in;
}
friend ostream& operator<< (ostream& out, const BigInt& t) {
out << t.to_string();
return out;
}
friend const BigInt operator+ (const BigInt& t, const BigInt& s) {
BigInt ans, sub;
if (t.num.length() < s.num.length()) {
ans = s;
sub = t;
} else if (t.num.length() == s.num.length()) {
if (t.num < s.num) {
ans = s;
sub = t;
} else {
ans = t;
sub = s;
}
} else {
ans = t;
sub = s;
}
int sub_l = sub.num.length();
int ans_l = ans.num.length();
if (t.sign == s.sign) {
for (int i = 1; i <= sub_l; i++) {
ans.num[ans_l - i] += sub.num[sub_l - i] - '0';
}
int flag = 0;
for (int i = 1; i <= ans_l; i++) {
if (ans.num[ans_l - i] > '9') {
ans.num[ans_l - i] -= 10;
if (i == ans_l) {
flag = 1;
} else {
ans.num[ans_l - i - 1] += 1;
}
} else if (i >= sub_l) {
break;
}
}
if (flag) ans.num = "1" + ans.num;
} else {
for (int i = 1; i <= sub_l; i++) {
ans.num[ans_l - i] -= sub.num[sub_l - i] - '0';
}
for (int i = 1; i <= ans_l; i++) {
if (ans.num[ans_l - i] < '0') {
ans.num[ans_l - i] += 10;
ans.num[ans_l - i - 1] -= 1;
} else if (i >= sub_l) {
break;
}
}
int flag = 0;
while (flag < ans_l - 1 && ans.num[flag] == '0') flag++;
ans.num = ans.num.substr(flag);
if (ans.num == "0") ans.sign = "+";
}
return ans;
}
friend const BigInt operator- (const BigInt& t, const BigInt& s) {
BigInt sub = s;
if (sub.sign == "+") sub.sign = "-";
else sub.sign = "+";
return t + sub;
}
friend const BigInt operator* (const BigInt& t, const BigInt& s) {
BigInt res;
if (s.sign == t.sign) res.sign = "+";
else res.sign = "-";
vector<complex<double> > x1, x2;
vector<int> sum;
string str1 = t.num, str2 = s.num;
int len1 = str1.length();
int len2 = str2.length();
int len = 1;
while (len < len1 * 2 || len < len2 * 2) len <<= 1;
for (int i = 0; i < len1; i++) {
x1.push_back(complex<double>(str1[len1 - 1 - i] - '0', 0));
}
for (int i = len1; i < len; i++) {
x1.push_back(complex<double>(0, 0));
}
for (int i = 0; i < len2; i++) {
x2.push_back(complex<double>(str2[len2 - 1 -i] - '0', 0));
}
for (int i = len2; i < len; i++) {
x2.push_back(complex<double>(0, 0));
}
fft(x1, 1);
fft(x2, 1);
for (int i = 0; i < len; i++) x1[i] = x1[i] * x2[i];
fft(x1, -1);
for (auto& i : x1) sum.push_back((int)(i.real() + 0.5));
for (int i = 0; i < len; i++) {
sum[i + 1] += sum[i] / 10;
sum[i] %= 10;
}
len = len1 + len2 - 1;
while (sum[len] <= 0 && len > 0) len--;
res.num = "";
for (int i = len; i >= 0; i--) res.num += sum[i] + '0';
if (res.num == "0") res.sign = "+";
return res;
}
friend const BigInt operator/ (const BigInt& t, const BigInt& s) {
if (s == 0) throw;
BigInt res;
if (s.sign == t.sign) res.sign = "+";
else res.sign = "-";
BigInt sub = abs(t), ans = abs(s);
int w = sub.num.length() - ans.num.length();
for (int i = 0; i < w; i++) ans.num += "0";
while (w >= 0) {
int d = 0;
while (ans <= sub) {
sub -= ans;
d++;
}
res.num += d + '0';
ans.num = ans.num.substr(0, ans.num.length() - 1);
w--;
}
int flag = 0;
while (flag < (int)res.num.length() - 1 && res.num[flag] == '0') flag++;
res.num = res.num.substr(flag);
if (res.num == "0") res.sign = "+";
return res;
}
friend const BigInt operator% (const BigInt& t, const BigInt& s) {
if (s == 0) throw;
BigInt sub = abs(t), ans = abs(s);
int w = sub.num.length() - ans.num.length();
for (int i = 0; i < w; i++) ans.num += "0";
while (w >= 0) {
int d = 0;
while (ans <= sub) {
sub -= ans;
d++;
}
w--;
ans.num = ans.num.substr(0, ans.num.length() - 1);
}
sub.sign = t.sign;
if (sub.num == "0") sub.sign = "+";
return sub;
}
friend BigInt& operator+= (BigInt& t, const BigInt& s) {
return t = t + s;
}
friend BigInt& operator-= (BigInt& t, const BigInt& s) {
return t = t - s;
}
friend BigInt& operator*= (BigInt& t, const BigInt& s) {
return t = t * s;
}
friend BigInt& operator/= (BigInt& t, const BigInt& s) {
return t = t / s;
}
friend BigInt& operator%= (BigInt& t, const BigInt& s) {
return t = t % s;
}
const BigInt subnum(int r, int l) {
BigInt ans = this->num.substr(this->num.length() - l, l - r);
ans.sign = this->sign;
return ans;
}
const BigInt subnum(int l) {
return this->subnum(0, l);
}
};
BigInt dp[110][110];
void init()
{
dp[0][0] = 1;
for(int i = 1; i <= 51; i++) {
dp[i][0] = 1;
for(int j = 1; j <= i; j++) {
dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1];
}
}
}
BigInt expo[2000];
BigInt f[52];
int main(int argc, char const *argv[]) {
init();
int n;
expo[0] = 1;
for(long long i = 1; i <= 1250; i++) {
expo[i] = 2LL * expo[i - 1];
}
f[1] = 1;
f[2] = 1;
while(std::cin >> n) {
if(n == 0) break;
if(n <= 2) {
std::cout << "1" << '\n';
continue;
}
BigInt tmp = 0;
for(int i = 3; i <= n; i++) {
BigInt tot = expo[(i * (i - 1) >> 1)];
// std::cout << "tot = " << tot << '\n';
for(int j = 1; j <= i - 1; j++) {
tot = tot - f[j] * dp[i - 1][j - 1] * expo[((i - j) * ((i - j) - 1)) >> 1];
}
f[i] = tot;
}
std::cout << f[n] << '\n';
}
return 0;
}

POJ 1737 Connected Graph (大数+递推)的更多相关文章

  1. poj 1737 Connected Graph

    // poj 1737 Connected Graph // // 题目大意: // // 带标号的连通分量计数 // // 解题思路: // // 设f(n)为连通图的数量,g(n)为非连通图的数量 ...

  2. POJ 1737 Connected Graph 题解(未完成)

    Connected Graph Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 3156   Accepted: 1533 D ...

  3. POJ 1737 Connected Graph(高精度+DP递推)

    题面 \(solution:\) 首先做个推销:带负数的压位高精度(加减乘+读写) 然后:由 \(N\) 个节点组成的无向图的总数为: \(2^{N*(N-1)/2}\) (也就是说这个图总共有 \( ...

  4. poj 3744 Scout YYF I(递推求期望)

    poj 3744 Scout YYF I(递推求期望) 题链 题意:给出n个坑,一个人可能以p的概率一步一步地走,或者以1-p的概率跳过前面一步,问这个人安全通过的概率 解法: 递推式: 对于每个坑, ...

  5. HDU-1041-Computer Transformation,大数递推,水过~~

                                                                                  Computer Transformatio ...

  6. POJ 1664 放苹果 (递推思想)

    原题链接:http://poj.org/problem?id=1664 思路:苹果m个,盘子n个.假设 f ( m , n ) 代表 m 个苹果,n个盘子有 f ( m , n ) 种放法. 根据 n ...

  7. 【POJ】2229 Sumsets(递推)

    Sumsets Time Limit: 2000MS   Memory Limit: 200000K Total Submissions: 20315   Accepted: 7930 Descrip ...

  8. POJ 3734 Blocks (线性递推)

    定义ai表示红色和绿色方块中方块数为偶数的颜色有i个,i = 0,1,2. aij表示刷到第j个方块时的方案数,这是一个线性递推关系. 可以构造递推矩阵A,用矩阵快速幂求解. /*********** ...

  9. POJ 3046 Ant Counting(递推,和号优化)

    计数类的问题,要求不重复,把每种物品单独考虑. 将和号递推可以把转移优化O(1). f[i = 第i种物品][j = 总数量为j] = 方案数 f[i][j] = sigma{f[i-1][j-k], ...

随机推荐

  1. 修改cloudera manager的端口号

    最近想在测试机装一个hadoop测试集群debug玩玩,然后就用cloudera manager装吧 这回使用rpm安装失败了,在网上搜到Cloudera Manager 5和CDH5离线安装说需要用 ...

  2. CCNP路由实验之六 动态路由协议之IS-IS

     CCNP路由实验之六动态路由协议之IS-IS 动态路由协议能够自己主动的发现远程网络.仅仅要网络拓扑结构发生了变化.路由器就会相互交换路由信息,不仅能够自己主动获知新添加的网络.还能够在当前网络 ...

  3. 思科E3200 路由器 DD-WRT 设置花生壳和3322.org动态域名(DDNS)

    花生壳设置(已測试) ddns.oray.com:80 username   aaaa password bbbb 主机名   abc.gicp.net URL       /ph/update?ho ...

  4. Android页面事件挂接模拟

    Java没有C#的引用类型.因此事件的挂接一般都是利用接口来实现,有两种方式: 1)定义一个实现事件接口的类,然后实现接口方法,然后通过将这个类的实例加入到事件监听器里面: public class ...

  5. modSecurity规则学习(四)——规则指令编写

    规则语言是使用9个指令实现: 语法:SecRule VARIABLES OPERATOR [TRANSFORMATION_FUNCTIONS, ACTIONS] Variables 以下几种: Reg ...

  6. 17. IntelliJ IDEA + Maven创建Java Web项目

    转自:https://www.cnblogs.com/Terry-Wu/p/8006475.html 1. Maven简介 相对于传统的项目,Maven 下管理和构建的项目真的非常好用和简单,所以这里 ...

  7. POJ 1671 第二类斯特林数

    思路: 递推出来斯特林数 求个和 if(i==j)f[i][j]=1; else f[i][j]=f[i-1][j-1]+f[i-1][j]*j; //By SiriusRen #include &l ...

  8. BZOJ 1578 DP

    思路:裸的完全背包 //By SiriusRen #include <cstdio> #include <cstring> #include <algorithm> ...

  9. HDU 5358 First One 数学+尺取法

    多校的题,摆明了数学题,但是没想出来,蠢爆了,之前算了半天的s[i][j]的和,其实是积.其实比赛的时候我连log(s[i][j])+1是s[i][j]的位数都没看出来,说出来都丢人. 知道了这个之后 ...

  10. 用Struts2搭建一个登录例子【本人亲测好用】

    今天尝试struts2的搭建,遇到不少的问题,终于一一解决,逛了很多地方,最终完成搭建 1.首先要下载struts2的一些组件,我下载的是版本2.3.4.1,Eclipse是4.6版本的.由于版本的不 ...