题目链接:

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. 转载-- Qt Creator编译时make: arm-linux-g++: command not found 错误!

    前提是已经配置好交叉编译器,但是qt creator找不到. 解决方法: 修改 /usr/local/Trolltech/QtEmbedded-4.7.0-arm/mkspecs/qws/linux- ...

  2. c#+ArcGIS Engine-获取矢量图层的空间参考

    转自原文c#+ArcGIS Engine-获取矢量图层的空间参考 介绍一种简单的获取矢量图层空间参考的方法: 首先打开Shp文件获得FeatureClass,代码如下: string pPath=&q ...

  3. [Poi] Use Markdown as React Components by Adding a Webpack Loader to Poi

    Poi ships with many webpack loaders included, but you may run into scenarios where you'll need to cu ...

  4. quick 3.3载入Spine问题

    近期项目要升级到Quick 3.3, 而且使用了Spine作为动画编辑器, 在此把升级过程中.有关quick 3.3 载入Spine遇到的坑在此记录一下. 1.Spine版本号问题 首先Quick 3 ...

  5. CSS 相对/绝对(relative/absolute)定位与jQuery的控制显示隐藏

    曾经写显示隐藏老是用jq方法控制: dom.show(); dom.hide(); 事实上这样还是有非常多缺陷的. 这是html结构: <div class="holi"&g ...

  6. .net core的安装

    安装完成后的路径在C:\Program Files\dotnet https://github.com/dotnet/cli/issues/390 ===2017年06月29日=== 安装成功之后,配 ...

  7. Lesson 2 Building your first web page: Part 1

    In this ‘hands-on’ module we will be building our first web page in no time. We just need to quickly ...

  8. C#中如何获得两个日期之间的天数差

    DateTime d1; DateTime d2; //自己去赋值吧 int days = (d1 - d2).Days;//天数差 label1.Text = "2012-1-1 15:3 ...

  9. Sub Thread to update main Thread (UI)

    Sub Thread to update main Thread (UI) main Thread :   A  has Hander.HandleMessage() to process the & ...

  10. 原生ajax实现方式

    http://www.cnblogs.com/rubylouvre/archive/2013/01/08/2851051.html <!DOCTYPE html> <html lan ...