题目链接

http://acm.hdu.edu.cn/showproblem.php?pid=1134

题意

给出一个n 然后有2n个点 给两个点连一条边,最后连N条边,要求所有的边不能够交叉 问最多有几分连边的方式

思路

我们可以发现 一个点 可以和它相隔偶数个点 的点连一条边

如果相隔奇数个点 比如说

那么 2号点 要是想连一条边 必然会经过点1和点3 连的边 就会交叉

如果相隔偶数的话

比如说

这种 其余四个点 就可以连边

或者 这种

1-4 这条边的 两边各有两个点 他们就能够连边

那怎么算答案呢

用dp[i] 来保存 i == n 时候的答案

显然 dp[1] = 1;

然后其他的答案 都是可以通过前面的答案 更新的

比如说

这一种 剩下的四个点 连边 其实是一个递归的子问题 显然 答案就是dp[4]

那么下面这种

也是递归的子问题

有一个坑点就是 答案可能很大 要用大数

用java 的大数模板类 或者 c++ 写个大数模板 都可以

因为 n = 100 的时候 答案 57 位多

我本来想用 long double 存答案的 但是 发现 数据大了后 答案就不正确了

因为 乘法 可能会导致精度的问题

比如说

10000000000000 * 12.0000000000002

这个结果 进位成整数就是有问题的

积少成多 自然 越到后面 答案越是有偏差

AC代码

#include <cstdio>
#include <cstring>
#include <ctype.h>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <map>
#include <stack>
#include <set>
#include <list>
#include <numeric>
#include <sstream>
#include <iomanip>
#include <limits> #define CLR(a, b) memset(a, (b), sizeof(a))
#define pb push_back
#define bug puts("***bug***");
#define fi first
#define se second
#define stack_expand #pragma comment(linker, "/STACK:102400000,102400000")
#define syn_close ios::sync_with_stdio(false);cin.tie(0);
#define sp system("pause");
//#define bug
//#define gets gets_s using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef pair <string, int> psi;
typedef pair <string, string> pss;
typedef pair <double, int> pdi; const double PI = acos(-1.0);
const double E = exp(1.0);
const double eps = 1e-8; const int INF = 0x3f3f3f3f;
const int maxn = 4e4 + 1e3 + 10;
const int MOD = 142857; #define MAXN 9999
#define MAXSIZE 10
#define DLEN 4
class BigNum
{
private:
int a[500]; //可以控制大数的位数
int len; //大数长度
public:
BigNum() { len = 1; memset(a, 0, sizeof(a)); } //构造函数
BigNum(const int); //将一个int类型的变量转化为大数
BigNum(const char*); //将一个字符串类型的变量转化为大数
BigNum(const BigNum &); //拷贝构造函数
BigNum &operator=(const BigNum &); //重载赋值运算符,大数之间进行赋值运算 friend istream& operator>>(istream&, BigNum&); //重载输入运算符
friend ostream& operator<<(ostream&, BigNum&); //重载输出运算符 BigNum operator+(const BigNum &) const; //重载加法运算符,两个大数之间的相加运算
BigNum operator-(const BigNum &) const; //重载减法运算符,两个大数之间的相减运算
BigNum operator*(const BigNum &) const; //重载乘法运算符,两个大数之间的相乘运算
BigNum operator/(const int &) const; //重载除法运算符,大数对一个整数进行相除运算 BigNum operator^(const int &) const; //大数的n次方运算
int operator%(const int &) const; //大数对一个int类型的变量进行取模运算
bool operator>(const BigNum & T)const; //大数和另一个大数的大小比较
bool operator>(const int & t)const; //大数和一个int类型的变量的大小比较 void print(); //输出大数
};
BigNum::BigNum(const int b) //将一个int类型的变量转化为大数
{
int c, d = b;
len = 0;
memset(a, 0, sizeof(a));
while (d > MAXN)
{
c = d - (d / (MAXN + 1)) * (MAXN + 1);
d = d / (MAXN + 1);
a[len++] = c;
}
a[len++] = d;
}
BigNum::BigNum(const char*s) //将一个字符串类型的变量转化为大数
{
int t, k, index, l, i;
memset(a, 0, sizeof(a));
l = strlen(s);
len = l / DLEN;
if (l%DLEN)
len++;
index = 0;
for (i = l - 1; i >= 0; i -= DLEN)
{
t = 0;
k = i - DLEN + 1;
if (k<0)
k = 0;
for (int j = k; j <= i; j++)
t = t * 10 + s[j] - '0';
a[index++] = t;
}
}
BigNum::BigNum(const BigNum & T) : len(T.len) //拷贝构造函数
{
int i;
memset(a, 0, sizeof(a));
for (i = 0; i < len; i++)
a[i] = T.a[i];
}
BigNum & BigNum::operator=(const BigNum & n) //重载赋值运算符,大数之间进行赋值运算
{
int i;
len = n.len;
memset(a, 0, sizeof(a));
for (i = 0; i < len; i++)
a[i] = n.a[i];
return *this;
}
istream& operator>>(istream & in, BigNum & b) //重载输入运算符
{
char ch[MAXSIZE * 4];
int i = -1;
in >> ch;
int l = strlen(ch);
int count = 0, sum = 0;
for (i = l - 1; i >= 0;)
{
sum = 0;
int t = 1;
for (int j = 0; j<4 && i >= 0; j++, i--, t *= 10)
{
sum += (ch[i] - '0')*t;
}
b.a[count] = sum;
count++;
}
b.len = count++;
return in; }
ostream& operator<<(ostream& out, BigNum& b) //重载输出运算符
{
int i;
cout << b.a[b.len - 1];
for (i = b.len - 2; i >= 0; i--)
{
cout.width(DLEN);
cout.fill('0');
cout << b.a[i];
}
return out;
} BigNum BigNum::operator+(const BigNum & T) const //两个大数之间的相加运算
{
BigNum t(*this);
int i, big; //位数
big = T.len > len ? T.len : len;
for (i = 0; i < big; i++)
{
t.a[i] += T.a[i];
if (t.a[i] > MAXN)
{
t.a[i + 1]++;
t.a[i] -= MAXN + 1;
}
}
if (t.a[big] != 0)
t.len = big + 1;
else
t.len = big;
return t;
}
BigNum BigNum::operator-(const BigNum & T) const //两个大数之间的相减运算
{
int i, j, big;
bool flag;
BigNum t1, t2;
if (*this>T)
{
t1 = *this;
t2 = T;
flag = 0;
}
else
{
t1 = T;
t2 = *this;
flag = 1;
}
big = t1.len;
for (i = 0; i < big; i++)
{
if (t1.a[i] < t2.a[i])
{
j = i + 1;
while (t1.a[j] == 0)
j++;
t1.a[j--]--;
while (j > i)
t1.a[j--] += MAXN;
t1.a[i] += MAXN + 1 - t2.a[i];
}
else
t1.a[i] -= t2.a[i];
}
t1.len = big;
while (t1.a[t1.len - 1] == 0 && t1.len > 1)
{
t1.len--;
big--;
}
if (flag)
t1.a[big - 1] = 0 - t1.a[big - 1];
return t1;
} BigNum BigNum::operator*(const BigNum & T) const //两个大数之间的相乘运算
{
BigNum ret;
int i, j, up;
int temp, temp1;
for (i = 0; i < len; i++)
{
up = 0;
for (j = 0; j < T.len; j++)
{
temp = a[i] * T.a[j] + ret.a[i + j] + up;
if (temp > MAXN)
{
temp1 = temp - temp / (MAXN + 1) * (MAXN + 1);
up = temp / (MAXN + 1);
ret.a[i + j] = temp1;
}
else
{
up = 0;
ret.a[i + j] = temp;
}
}
if (up != 0)
ret.a[i + j] = up;
}
ret.len = i + j;
while (ret.a[ret.len - 1] == 0 && ret.len > 1)
ret.len--;
return ret;
}
BigNum BigNum::operator/(const int & b) const //大数对一个整数进行相除运算
{
BigNum ret;
int i, down = 0;
for (i = len - 1; i >= 0; i--)
{
ret.a[i] = (a[i] + down * (MAXN + 1)) / b;
down = a[i] + down * (MAXN + 1) - ret.a[i] * b;
}
ret.len = len;
while (ret.a[ret.len - 1] == 0 && ret.len > 1)
ret.len--;
return ret;
}
int BigNum::operator %(const int & b) const //大数对一个int类型的变量进行取模运算
{
int i, d = 0;
for (i = len - 1; i >= 0; i--)
{
d = ((d * (MAXN + 1)) % b + a[i]) % b;
}
return d;
}
BigNum BigNum::operator^(const int & n) const //大数的n次方运算
{
BigNum t, ret(1);
int i;
if (n<0)
exit(-1);
if (n == 0)
return 1;
if (n == 1)
return *this;
int m = n;
while (m>1)
{
t = *this;
for (i = 1; i << 1 <= m; i <<= 1)
{
t = t * t;
}
m -= i;
ret = ret * t;
if (m == 1)
ret = ret * (*this);
}
return ret;
}
bool BigNum::operator>(const BigNum & T) const //大数和另一个大数的大小比较
{
int ln;
if (len > T.len)
return true;
else if (len == T.len)
{
ln = len - 1;
while (a[ln] == T.a[ln] && ln >= 0)
ln--;
if (ln >= 0 && a[ln] > T.a[ln])
return true;
else
return false;
}
else
return false;
}
bool BigNum::operator >(const int & t) const //大数和一个int类型的变量的大小比较
{
BigNum b(t);
return *this>b;
} void BigNum::print() //输出大数
{
int i;
cout << a[len - 1];
for (i = len - 2; i >= 0; i--)
{
cout.width(DLEN);
cout.fill('0');
cout << a[i];
}
cout << endl;
} BigNum dp[110]; void init()
{
dp[0] = (BigNum)1;
dp[1] = (BigNum)1;
for (int i = 2; i <= 100; i++)
{
dp[i] = (BigNum)0;
for (int j = 0; j <= 2 * i - 2; j += 2)
{
dp[i] = dp[i] + dp[j / 2] * dp[(2 * i - 2 - j) / 2];
}
}
} int main()
{
init();
int n;
while (scanf("%d", &n) && n != -1)
dp[n].print();
}

HDU - 1134 Game of Connections 【DP】的更多相关文章

  1. hdu 6169 gems gems gems【DP】

    题目链接:hdu 6169 gems gems gems Now there are n gems, each of which has its own value. Alice and Bob pl ...

  2. HDU 1069—— Monkey and Banana——————【dp】

    Monkey and Banana Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u S ...

  3. hdu 1078 FatMouse and Cheese【dp】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1078 题意:每次仅仅能走 横着或竖着的 1~k 个格子.求最多能吃到的奶酪. 代码: #include ...

  4. HDU - 1160 FatMouse's Speed 【DP】

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1160 题意 给出一系列的 wi si 要找出一个最长的子序列 满足 wi 是按照升序排列的 si 是按 ...

  5. hdu 1503 LCS输出路径【dp】

    hdu 1503 不知道最后怎么输出,因为公共部分只输出一次.有人说回溯输出,感觉好巧妙!其实就是下图,输出的就是那条灰色的路径,但是初始时边界一定要初始化一下,因为最第一列只能向上走,第一行只能向左 ...

  6. HDU 2577 How to Type【DP】

    题意:给出一个字符串,有大写有小写,问最少的按键次数.然后打字的这个人有一个习惯,打完所有的字之后,指示灯要关闭. dp[i][j]表示打到第i个字母,j有0,1两个值表示指示灯开或者关的状态 然后就 ...

  7. HDU 5656 ——CA Loves GCD——————【dp】

    CA Loves GCD Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)To ...

  8. hdu 1003 hdu 1231 最大连续子序列【dp】

    HDU1003 HDU1231 题意自明.可能是真的进步了点,记得刚开始研究这个问题时还想了好长时间,hdu 1231还手推了很长时间,今天重新写干净利落就AC了. #include<iostr ...

  9. HDOJ_1087_Super Jumping! Jumping! Jumping! 【DP】

    HDOJ_1087_Super Jumping! Jumping! Jumping! [DP] Time Limit: 2000/1000 MS (Java/Others) Memory Limit: ...

随机推荐

  1. 嵌套矩形——DAG上的动态规划

    有向无环图(DAG,Directed Acyclic Graph)上的动态规划是学习动态规划的基础.非常多问题都能够转化为DAG上的最长路.最短路或路径计数问题. 题目描写叙述: 有n个矩形,每一个矩 ...

  2. STL学习笔记(非变动性算法)

    辅助函数 本节跟以后几节将对所有STL算法逐一详细讨论.为了简化这些例子,我们使用了一些辅助函数,分别用于对容器进行输出跟插入操作. #ifndef ALGOSTUFF_HPP #define ALG ...

  3. Cocos2d-X中创建菜单项

    Cocos2d-X中创建菜单的类: CCMenuItemFont:创建纯文本的菜单项 CCMenuItemAtlasFont:创建带有艺术字体的菜单项 CCMenuItemImage:用图片创建菜单项 ...

  4. iOS项目开发之实现无限轮播

    简介 分析 实现 代码下载 一.简介 在实际的开发当中,会经常有界面需要实现图片的无限轮播这样的需求.比如新闻app,或者其他app的广告位 实现的方式有很多种,最先想动的一定是scrollView, ...

  5. Eclipse更改默认工作环境编码为UTF-8(9.6)

    1 window---->preference------>General----->Workspace---->Text file encoding---->Other ...

  6. 【hadoop之翊】——windows 7使用eclipse下hadoop应用开发环境搭建

    由于一些缘故,这节内容到如今才写.事实上弄hadoop有一段时间了,能够编写一些小程序了,今天来还是来说说环境的搭建.... 说明一下:这篇文章的步骤是接上一篇的hadoop文章的:http://bl ...

  7. python char()和ord()

    通过help 查看相关函数的帮助文档 >>>help (chr) chr(...) chr(i) -> character Return a string of one cha ...

  8. MVC进阶学习--View和Controller之间的数据传递(一)

    1.使用ViewData ViewData 的是ControllerBase 的一个属性,是一个数据字典类型的,其实现代码如(这段代码来自asp.net MVC开源项目中源码)下: Code   1  ...

  9. JavaScript_DOM编程艺术第二版[阅]

    前两年迫于项目的需要,只是拿来JQuery用到项目中,并没有实质上理解javascript(貌似其他人也是这么干的)~ 随着最近几年,得益于Nodejs, React, Vue等,javascript ...

  10. java.io.IOException: Illegal partition for 67 (-1)

    今天写MapReduce的分区进行排序的功能,自己写了一个Partitioner,然后用的时候就错了 public static class MyPartition extends Partition ...