- 浏览: 10932 次
- 性别:
- 来自: 北京
最近访客 更多访客>>
文章分类
- 全部博客 (6)
- 算法理论学习 (0)
- 最小限度生成树 (0)
- 最小生成树 (0)
- 最短路径 (0)
- 最大流 (0)
- 组合数学 (2)
- 杂 (0)
- 线段树 (0)
- 位运算 (0)
- 贪心 (0)
- 数论 (0)
- 树状数组 (1)
- 强连通分量 (0)
- 欧拉问题 (0)
- 模拟 (0)
- 枚举 (0)
- 矩阵运算 (0)
- 简单数据结构的应用 (0)
- 计算几何 (1)
- 哈希 (0)
- 割点 (0)
- 高斯消元 (0)
- 高精度 (0)
- 复杂数据结构 (0)
- 二分图 (0)
- 二分法 (0)
- 堆栈 (1)
- 堆结构 (0)
- 动态规划 (0)
- 点连通度 边连通度 割点 割边 (0)
- 典型递归应用 (0)
- 递推 (0)
- 差分约束系统 (0)
- 博弈 (0)
- 并查集 (0)
- Trie树 (0)
- LCA Tarjan (0)
- KMP (0)
- Floyd 及其扩展算法(最小代价回路) (0)
- DFS (0)
- BFS (0)
- BellmanFord & spfa (0)
- A* (0)
最新评论
-
talenx:
infix => postfix => infix ...
去除表达式里面多余的() -
spyker:
正则表达式可以解决不 环视+引用可以用哪个试试
去除表达式里面多余的() -
bobten2008:
qq240996777 写道我觉得用栈好点吧
嗯,呵呵。我用的 ...
去除表达式里面多余的() -
qq240996777:
我觉得用栈好点吧
去除表达式里面多余的() -
bobten2008:
roy 写道不好意思,还没看代码,但有个问题
输入:12+(3 ...
去除表达式里面多余的()
Game of Connections
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 4839 | Accepted: 2515 |
Description
This is a small but ancient game. You are supposed to write down the numbers 1, 2, 3, . . . , 2n - 1, 2n consecutively in clockwise order on the ground to form a circle, and then, to draw some straight line segments to connect them into number pairs. Every number must be connected to exactly one another.
And, no two segments are allowed to intersect.
It's still a simple game, isn't it? But after you've written down the 2n numbers, can you tell me in how many different ways can you connect the numbers into pairs? Life is harder, right?
And, no two segments are allowed to intersect.
It's still a simple game, isn't it? But after you've written down the 2n numbers, can you tell me in how many different ways can you connect the numbers into pairs? Life is harder, right?
Input
Each line of the input file will be a single positive number n, except the last line, which is a number -1.
You may assume that 1 <= n <= 100.
You may assume that 1 <= n <= 100.
Output
For each n, print in a single line the number of ways to connect the 2n numbers into pairs.
Sample Input
2 3 -1
Sample Output
2 5
Source
/*
卡特兰数 + 大数运算,一开始自己推公式得到的结论是:
f(2 * n) = f(0) * f(2 * n - 2) + f(2) * f(2 * n - 4) + f(4) * f(2 * n - 6) + ... + f(2 * n - 2) * f(0);
然后纯粹基于递推来算, 发现结果是对的,但是速度太慢,超时了。后来想了想,这不就是卡特兰数吗?呵呵,问题解决了
F(n) = F(0) * F(n - 1) + F(1) * F(n - 2) + ... + F(n - 1) * F(0) = C(2 * n, n) / (n + 1), F(0) = 1
代码很长,大部分是自己写的大数运算工具模板, 哈哈
*/
卡特兰数 + 大数运算,一开始自己推公式得到的结论是:
f(2 * n) = f(0) * f(2 * n - 2) + f(2) * f(2 * n - 4) + f(4) * f(2 * n - 6) + ... + f(2 * n - 2) * f(0);
然后纯粹基于递推来算, 发现结果是对的,但是速度太慢,超时了。后来想了想,这不就是卡特兰数吗?呵呵,问题解决了
F(n) = F(0) * F(n - 1) + F(1) * F(n - 2) + ... + F(n - 1) * F(0) = C(2 * n, n) / (n + 1), F(0) = 1
代码很长,大部分是自己写的大数运算工具模板, 哈哈
*/
#include <iostream> #include <string> #define BIGINTEGER_LEN_TYPE int #define MAX_N 201 using namespace std; string num[MAX_N]; string cval[MAX_N][MAX_N]; //大数加法 string bigIntegerAdd(const string left, const string right) { BIGINTEGER_LEN_TYPE lenl = static_cast<BIGINTEGER_LEN_TYPE>(left.size()); BIGINTEGER_LEN_TYPE lenr = static_cast<BIGINTEGER_LEN_TYPE>(right.size()); std::string res = ""; //get the minimum length of the two string BIGINTEGER_LEN_TYPE minLen = (lenl <= lenr) ? lenl : lenr; BIGINTEGER_LEN_TYPE maxLen = (lenl <= lenr) ? lenr : lenl; std::string longerStr = (lenl <= lenr) ? right : left; int residue = 0, sum = 0, quotient = 0; //add operation, first part BIGINTEGER_LEN_TYPE pos1; for(pos1 = 0; pos1 <= minLen - 1; pos1++) { sum = (left[pos1] - '0') + (right[pos1] - '0') + quotient; quotient = sum / 10; residue = sum % 10; res += residue + '0'; } //add operation, second part for(BIGINTEGER_LEN_TYPE pos2 = pos1; pos2 <= maxLen - 1; pos2 ++) { sum = (longerStr[pos2] - '0') + quotient; quotient = sum / 10; residue = sum % 10; res += residue + '0'; } //add the extra carry while(quotient != 0) { residue = quotient % 10; quotient = quotient / 10; res += residue + '0'; } //std::cout<<"res size:"<<res.length()<<std::endl; return res; } //大数乘法 string bigIntegerMult(const string left, const string right) { BIGINTEGER_LEN_TYPE minLen = static_cast<BIGINTEGER_LEN_TYPE>(left.length()); BIGINTEGER_LEN_TYPE maxLen = static_cast<BIGINTEGER_LEN_TYPE>(right.length()); std::string longerStr = ""; std::string shorterStr = ""; std::string res = ""; //get the longer and short strings and corresponded length if(left.length() <= right.length()) { minLen = static_cast<BIGINTEGER_LEN_TYPE>(left.length()); maxLen = static_cast<BIGINTEGER_LEN_TYPE>(right.length()); shorterStr = left; longerStr = right; } else { minLen = static_cast<BIGINTEGER_LEN_TYPE>(right.length()); maxLen = static_cast<BIGINTEGER_LEN_TYPE>(left.length()); shorterStr = right; longerStr = left; } BIGINTEGER_LEN_TYPE pos1 = 0; BIGINTEGER_LEN_TYPE pos2 = 0; //start from the first digit of the shorter string for(pos1 = 0; pos1 <= minLen - 1; pos1++) { //multiply each digit of the longer string int residue = 0, product = 0, quotient = 0; BIGINTEGER_LEN_TYPE curPos = 0; for(pos2 = 0; pos2 <= maxLen - 1; pos2++) { curPos = pos1 + pos2; //new space if(res.length() == 0 || curPos > int(res.length() - 1)) { product = (shorterStr[pos1] - '0') * (longerStr[pos2] - '0') + quotient; quotient = product / 10; residue = product % 10; res += residue + '0'; } //space already exists, just add the original value to product else { product = (shorterStr[pos1] - '0') * (longerStr[pos2] - '0') + quotient + (res[curPos] - '0'); quotient = product / 10; residue = product % 10; res[curPos] = residue + '0'; } } //process the extra quotient //start position curPos = maxLen + pos1; while(quotient != 0) { if(res.length() == 0 || curPos > int(res.length() - 1)) { residue = quotient % 10; quotient = quotient / 10; res += residue + '0'; } else { quotient = quotient + (res[curPos] - '0'); residue = quotient % 10; quotient = quotient / 10; res[curPos] = residue + '0'; } curPos++; } } //std::cout<<res.length()<<std::endl; return res; } //对字符串str进行翻转 string getReverse(const string str) { std::string revStr = ""; BIGINTEGER_LEN_TYPE pos = static_cast<BIGINTEGER_LEN_TYPE>(str.length()) - 1; for(; pos >= 0; pos--) revStr += str[pos]; return revStr; } //比较两个大数的大小 int bigIntegerCmp(const string left, const string right) { BIGINTEGER_LEN_TYPE lenl = static_cast<BIGINTEGER_LEN_TYPE>(left.length()); BIGINTEGER_LEN_TYPE lenr = static_cast<BIGINTEGER_LEN_TYPE>(right.length()); if(lenl < lenr) return -1; else if(lenl > lenr) return 1; return strcmp(getReverse(left).c_str(), getReverse(right).c_str()); } //大数减法 string bigIntegerSub(const string left, const string right) { std::string biggerStr = ""; std::string smallerStr = ""; std::string res = ""; BIGINTEGER_LEN_TYPE minLen = 0; BIGINTEGER_LEN_TYPE maxLen = 0; //get the bigger integer and smaller integer int cmpRes = bigIntegerCmp(left, right); if(cmpRes == -1 || cmpRes == 0) { smallerStr = left; biggerStr = right; } else { smallerStr = right; biggerStr = left; } //get related size minLen = static_cast<BIGINTEGER_LEN_TYPE>(smallerStr.length()); maxLen = static_cast<BIGINTEGER_LEN_TYPE>(biggerStr.length()); int extra = 0, temp = 0, subRes = 0; //subtraction operation, first part BIGINTEGER_LEN_TYPE pos1; for(pos1 = 0; pos1 <= minLen - 1; pos1++) { int curL = biggerStr[pos1] - '0'; int curR = smallerStr[pos1] - '0'; temp = 0; while((subRes = (curL - curR + 10 * temp - extra)) < 0) temp++; res += subRes + '0'; extra = temp; } //subtraction operation, second part for(BIGINTEGER_LEN_TYPE pos2 = pos1; pos2 <= maxLen - 1; pos2 ++) { int curL = biggerStr[pos2] - '0'; temp = 0; while((subRes = (curL + 10 * temp - extra)) < 0) temp++; res += subRes + '0'; extra = temp; } //remove the zero at head while(res[res.length() - 1] == '0' && res.length() >= 2) res = res.substr(0, res.length() - 1); //std::cout<<"res size:"<<res.length()<<std::endl; return res; } //把整数转换为字符串 string getStr(int a) { string res = ""; if(a == 0) return "0"; else { while(a) { res = char(a % 10 + '0') + res; a = a / 10; } } return res; } //大数除法 void bigIntegerDiv(const std::string left, const std::string right, std::string & quotient, std::string & residual) { int type = bigIntegerCmp(left, right); //left < right if(type == -1) { quotient = "0"; residual = left; return; } //left = right else if(type == 0) { quotient = "1"; residual = "0"; return; } //left > right //initialize the related data quotient = ""; residual = ""; std::string dividend = left; std::string divisor = right; BIGINTEGER_LEN_TYPE lenDend = static_cast<BIGINTEGER_LEN_TYPE>(left.length()); BIGINTEGER_LEN_TYPE lenDsor = static_cast<BIGINTEGER_LEN_TYPE>(right.length()); std::string temp = ""; std::string curStr = ""; std::string tryStr = ""; BIGINTEGER_LEN_TYPE curPos = 0; int choice = 0; bool visitedFirst = false; //start from the head of the dividend for(curPos = lenDend - 1; curPos >= 0; curPos--) { curStr = dividend[curPos] + curStr; //curStr > divisor, can be processed if(bigIntegerCmp(curStr, divisor) >= 0) { //try the quotient from 1 to 10 until the result of choice * divisor is the biggest less than curStr for(choice = 1; choice <= 10; choice++) { temp = ""; temp += char(choice + '0'); tryStr = bigIntegerMult(divisor, temp); if(bigIntegerCmp(tryStr, curStr) > 0) { choice--; break; } } //right now, choice is just the current quotient and should be appended ahead to quotient quotient = char(choice + '0') + quotient; temp = ""; temp += char(choice + '0'); //update curStr curStr = bigIntegerSub(curStr, bigIntegerMult(divisor, temp)); if(curPos == 0) residual = curStr; //set visitedFirst, visitedFirst is used to prevent producing '0' quotient visitedFirst = true; } //curStr is not enough to be divided by divisor, so the current quotient is '0' and should be appended to 'quotient' else if(visitedFirst) quotient = '0' + quotient; if(curPos == 0) { residual = curStr; break; } if(curStr == "0") curStr = ""; } residual = curStr; return; } string getCval(int p, int q) { if(p == q || q == 0) return "1"; if(q == 1) return getReverse(getStr(p)); if(cval[p][q] != "0") return cval[p][q]; return cval[p][q] = bigIntegerAdd(getCval(p - 1, q - 1), getCval(p - 1, q)); } //计算k的卡特兰数,下标从0开始 string solve1(int k) { if(num[k] != "0") return num[k]; string quotient, residual; bigIntegerDiv(getCval(2 * k, k), getReverse(getStr(k + 1)), quotient, residual); return quotient; } int main() { int i, j, p; for(i = 1; i < MAX_N; i++) { num[i] = "0"; for(j = 1; j < MAX_N; j++) cval[i][j] = "0"; } num[1] = "1"; while(scanf("%I64d", &p) && p != -1) cout<<getReverse(solve1(p))<<endl; return 0; }
相关推荐
北大POJ1027-The Same Game 解题报告+AC代码
北大POJ1753-Flip Game 解题报告+AC代码
poj 1353 Color Change of Go Game Pieces.md
poj 2771 Guardian of Decency.md
poj 3174 Alignment of the Planets.md
poj 2903 Joy of Mobile Routing.md
POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类
业余爱好。所以,算法不一定好,CODING也不一定佳,效率不一定高,只是能通过online judge而已。
北大POJ2151-Check the difficulty of problems 解题报告+AC代码
北大POJ2109-Power of Cryptography 解题报告+AC代码
poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题...
POJ2942-Knights of the Round Table 【Tarjan算法】 解题报告+AC代码 http://hi.csdn.net/!s/F3L8HO ================================== 我的POJ所有解题报告:...
poj 3901 The Computer Game.md
北大POJ2739-Sum of Consecutive Prime Numbers 解题报告+AC代码
北大POJ3083-Children of the Candy Corn 解题报告+AC代码
POJ第1861题源码 POJ第1861题源码 POJ第1861题源码
poj分类poj分类poj分类poj分类
北大POJ1159-Palindrome 解题报告+AC代码
poj 3414解题报告poj 3414解题报告poj 3414解题报告poj 3414解题报告
poj 1012解题报告poj 1012解题报告poj 1012解题报告poj 1012解题报告