hdu 1130How Many Trees?(卡特兰数)
Posted zhgyki
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 1130How Many Trees?(卡特兰数)相关的知识,希望对你有一定的参考价值。
卡特兰数又称卡塔兰数,英文名Catalan number,是组合数学中一个常出现在各种计数问题中出现的数列。
以比利时的数学家欧仁·查理·卡塔兰 (1814–1894)的名字来命名,其前几项为(从第零项开始) : 1, 1, 2, 5,
14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790,
477638700, 1767263190, 6564120420, 24466267020, 91482563640, 343059613650, 1289904147324,
4861946401452, ...
卡特兰数有几条递推式:
h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) (n>=2)
h(n)=h(n-1)*(4*n-2)/(n+1);
h(n)=C(2n,n)/(n+1)
h(n)=c(2n,n)-c(2n,n-1)
题意:找规律
代码:
#include<iostream> #include<vector> #include<deque> #include<string.h> #include<math.h> #include<stdio.h> #include<algorithm> #include<string> using namespace std; class DividedByZeroException {}; class BigInteger { private: vector<char> digits; bool sign; // true for positive, false for negitive void trim(); // remove zeros in tail, but if the value is 0, keep only one:) public: BigInteger(int); // construct with a int integer BigInteger(string&) ; BigInteger(); BigInteger(const BigInteger&); BigInteger operator=(const BigInteger& op2); BigInteger abs() const; BigInteger pow(int a); //binary operators friend BigInteger operator+=(BigInteger&, const BigInteger&); friend BigInteger operator-=(BigInteger&, const BigInteger&); friend BigInteger operator*=(BigInteger&, const BigInteger&); friend BigInteger operator/=(BigInteger&, const BigInteger&) throw(DividedByZeroException); friend BigInteger operator%=(BigInteger&, const BigInteger&) throw(DividedByZeroException); friend BigInteger operator+(const BigInteger&, const BigInteger&); friend BigInteger operator-(const BigInteger&, const BigInteger&); friend BigInteger operator*(const BigInteger&, const BigInteger&); friend BigInteger operator/(const BigInteger&, const BigInteger&) throw(DividedByZeroException); friend BigInteger operator%(const BigInteger&, const BigInteger&) throw(DividedByZeroException); //uniary operators friend BigInteger operator-(const BigInteger&); //negative friend BigInteger operator++(BigInteger&); //++v friend BigInteger operator++(BigInteger&, int); //v++ friend BigInteger operator--(BigInteger&); //--v friend BigInteger operator--(BigInteger&, int); //v-- friend bool operator>(const BigInteger&, const BigInteger&); friend bool operator<(const BigInteger&, const BigInteger&); friend bool operator==(const BigInteger&, const BigInteger&); friend bool operator!=(const BigInteger&, const BigInteger&); friend bool operator>=(const BigInteger&, const BigInteger&); friend bool operator<=(const BigInteger&, const BigInteger&); friend ostream& operator<<(ostream&, const BigInteger&); //print the BigInteger friend istream& operator>>(istream&, BigInteger&); // input the BigInteger public: static const BigInteger ZERO; static const BigInteger ONE; static const BigInteger TEN; }; const BigInteger BigInteger::ZERO = BigInteger(0); const BigInteger BigInteger::ONE = BigInteger(1); const BigInteger BigInteger::TEN = BigInteger(10); BigInteger::BigInteger() { sign = true; } BigInteger::BigInteger(int val) { // construct with a int integer if (val >= 0) { sign = true; } else { sign = false; val *= (-1); } do { digits.push_back((char)(val % 10)); val /= 10; } while (val != 0); } BigInteger::BigInteger(string& def) { sign = true; for (string::reverse_iterator iter = def.rbegin() ; iter < def.rend(); iter++) { char ch = (*iter); if (iter == def.rend() - 1) { if (ch == ‘+‘) { break; } if (ch == ‘-‘) { sign = false; break; } } digits.push_back((char)((*iter) - ‘0‘)); } trim(); } void BigInteger::trim() { vector<char>::reverse_iterator iter = digits.rbegin(); while (!digits.empty() && (*iter) == 0) { digits.pop_back(); iter = digits.rbegin(); } if (digits.size() == 0) { sign = true; digits.push_back(0); } } BigInteger::BigInteger(const BigInteger& op2) { sign = op2.sign; digits = op2.digits; } BigInteger BigInteger::operator=(const BigInteger& op2) { digits = op2.digits; sign = op2.sign; return (*this); } BigInteger BigInteger::abs() const { if (sign) { return *this; } else { return -(*this); } } BigInteger BigInteger::pow(int a) { BigInteger res(1); for (int i = 0; i < a; i++) { res *= (*this); } return res; } //binary operators BigInteger operator+=(BigInteger& op1, const BigInteger& op2) { if (op1.sign == op2.sign) { //只处理相同的符号的情况,异号的情况给-处理 vector<char>::iterator iter1; vector<char>::const_iterator iter2; iter1 = op1.digits.begin(); iter2 = op2.digits.begin(); char to_add = 0; //进位 while (iter1 != op1.digits.end() && iter2 != op2.digits.end()) { (*iter1) = (*iter1) + (*iter2) + to_add; to_add = ((*iter1) > 9); // 大于9进一位 (*iter1) = (*iter1) % 10; iter1++; iter2++; } while (iter1 != op1.digits.end()) { // (*iter1) = (*iter1) + to_add; to_add = ((*iter1) > 9); (*iter1) %= 10; iter1++; } while (iter2 != op2.digits.end()) { char val = (*iter2) + to_add; to_add = (val > 9) ; val %= 10; op1.digits.push_back(val); iter2++; } if (to_add != 0) { op1.digits.push_back(to_add); } return op1; } else { if (op1.sign) { return op1 -= (-op2); } else { return op1 = op2 - (-op1); } } } BigInteger operator-=(BigInteger& op1, const BigInteger& op2) { if (op1.sign == op2.sign) { //只处理相同的符号的情况,异号的情况给+处理 if (op1.sign) { if (op1 < op2) { // 2 - 3 return op1 = -(op2 - op1); } } else { if (-op1 > -op2) { // (-3)-(-2) = -(3 - 2) return op1 = -((-op1) - (-op2)); } else { // (-2)-(-3) = 3 - 2 return op1 = (-op2) - (-op1); } } vector<char>::iterator iter1; vector<char>::const_iterator iter2; iter1 = op1.digits.begin(); iter2 = op2.digits.begin(); char to_substract = 0; //借位 while (iter1 != op1.digits.end() && iter2 != op2.digits.end()) { (*iter1) = (*iter1) - (*iter2) - to_substract; to_substract = 0; if ((*iter1) < 0) { to_substract = 1; (*iter1) += 10; } iter1++; iter2++; } while (iter1 != op1.digits.end()) { (*iter1) = (*iter1) - to_substract; to_substract = 0; if ((*iter1) < 0) { to_substract = 1; (*iter1) += 10; } else { break; } iter1++; } op1.trim(); return op1; } else { if (op1 > BigInteger::ZERO) { return op1 += (-op2); } else { return op1 = -(op2 + (-op1)); } } } BigInteger operator*=(BigInteger& op1, const BigInteger& op2) { BigInteger result(0); if (op1 == BigInteger::ZERO || op2 == BigInteger::ZERO) { result = BigInteger::ZERO; } else { vector<char>::const_iterator iter2 = op2.digits.begin(); while (iter2 != op2.digits.end()) { if (*iter2 != 0) { deque<char> temp(op1.digits.begin(), op1.digits.end()); char to_add = 0; deque<char>::iterator iter1 = temp.begin(); while (iter1 != temp.end()) { (*iter1) *= (*iter2); (*iter1) += to_add; to_add = (*iter1) / 10; (*iter1) %= 10; iter1++; } if (to_add != 0) { temp.push_back(to_add); } int num_of_zeros = iter2 - op2.digits.begin(); while (num_of_zeros--) { temp.push_front(0); } BigInteger temp2; temp2.digits.insert(temp2.digits.end(), temp.begin(), temp.end()); temp2.trim(); result = result + temp2; } iter2++; } result.sign = ((op1.sign && op2.sign) || (!op1.sign && !op2.sign)); } op1 = result; return op1; } BigInteger operator/=(BigInteger& op1, const BigInteger& op2) throw(DividedByZeroException) { if (op2 == BigInteger::ZERO) { throw DividedByZeroException(); } BigInteger t1 = op1.abs(), t2 = op2.abs(); if (t1 < t2) { op1 = BigInteger::ZERO; return op1; } //现在 t1 > t2 > 0 //只需将 t1/t2的结果交给result就可以了 deque<char> temp; vector<char>::reverse_iterator iter = t1.digits.rbegin(); BigInteger temp2(0); while (iter != t1.digits.rend()) { temp2 = temp2 * BigInteger::TEN + BigInteger((int)(*iter)); char s = 0; while (temp2 >= t2) { temp2 = temp2 - t2; s = s + 1; } temp.push_front(s); iter++; } op1.digits.clear(); op1.digits.insert(op1.digits.end(), temp.begin(), temp.end()); op1.trim(); op1.sign = ((op1.sign && op2.sign) || (!op1.sign && !op2.sign)); return op1; } BigInteger operator%=(BigInteger& op1, const BigInteger& op2) throw(DividedByZeroException) { return op1 -= ((op1 / op2) * op2); } BigInteger operator+(const BigInteger& op1, const BigInteger& op2) { BigInteger temp(op1); temp += op2; return temp; } BigInteger operator-(const BigInteger& op1, const BigInteger& op2) { BigInteger temp(op1); temp -= op2; return temp; } BigInteger operator*(const BigInteger& op1, const BigInteger& op2) { BigInteger temp(op1); temp *= op2; return temp; } BigInteger operator/(const BigInteger& op1, const BigInteger& op2) throw(DividedByZeroException) { BigInteger temp(op1); temp /= op2; return temp; } BigInteger operator%(const BigInteger& op1, const BigInteger& op2) throw(DividedByZeroException) { BigInteger temp(op1); temp %= op2; return temp; } //uniary operators BigInteger operator-(const BigInteger& op) { //negative BigInteger temp = BigInteger(op); temp.sign = !temp.sign; return temp; } BigInteger operator++(BigInteger& op) { //++v op += BigInteger::ONE; return op; } BigInteger operator++(BigInteger& op, int x) { //v++ BigInteger temp(op); ++op; return temp; } BigInteger operator--(BigInteger& op) { //--v op -= BigInteger::ONE; return op; } BigInteger operator--(BigInteger& op, int x) { //v-- BigInteger temp(op); --op; return temp; } bool operator<(const BigInteger& op1, const BigInteger& op2) { if (op1.sign != op2.sign) { return !op1.sign; } else { if (op1.digits.size() != op2.digits.size()) return (op1.sign && op1.digits.size() < op2.digits.size()) || (!op1.sign && op1.digits.size() > op2.digits.size()); vector<char>::const_reverse_iterator iter1, iter2; iter1 = op1.digits.rbegin(); iter2 = op2.digits.rbegin(); while (iter1 != op1.digits.rend()) { if (op1.sign && *iter1 < *iter2) { return true; } if (op1.sign && *iter1 > *iter2) { return false; } if (!op1.sign && *iter1 > *iter2) { return true; } if (!op1.sign && *iter1 < *iter2) { return false; } iter1++; iter2++; } return false; } } bool operator==(const BigInteger& op1, const BigInteger& op2) { if (op1.sign != op2.sign || op1.digits.size() != op2.digits.size()) { return false; } vector<char>::const_iterator iter1, iter2; iter1 = op1.digits.begin(); iter2 = op2.digits.begin(); while (iter1 != op1.digits.end()) { if (*iter1 != *iter2) { return false; } iter1++; iter2++; } return true; } bool operator!=(const BigInteger& op1, const BigInteger& op2) { return !(op1 == op2); } bool operator>=(const BigInteger& op1, const BigInteger& op2) { return (op1 > op2) || (op1 == op2); } bool operator<=(const BigInteger& op1, const BigInteger& op2) { return (op1 < op2) || (op1 == op2); } bool operator>(const BigInteger& op1, const BigInteger& op2) { return !(op1 <= op2); } ostream& operator<<(ostream& stream, const BigInteger& val) { //print the BigInteger if (!val.sign) { stream << "-"; } for (vector<char>::const_reverse_iterator iter = val.digits.rbegin(); iter != val.digits.rend() ; iter++) { stream << (char)((*iter) + ‘0‘); } return stream; } istream& operator>>(istream& stream, BigInteger& val) { //Input the BigInteger string str; stream >> str; val = BigInteger(str); return stream; } #define maxn 105 BigInteger a[maxn]; int main() { int B; a[1]=1; for(int i=2;i<=maxn;i++) { a[i]=a[i-1]*(4*i-2)/(i+1); } while(cin >>B){ cout<<a[B]<<endl; } /*cout << "A-B:" << A - B << endl; cout << "A+B:" << A + B << endl; cout << "A*B:" << A*B << endl; cout << "A/B:" << A / B << endl; cout << "A%B:" << A % B << endl; cout << A.pow(B-3) << endl; A++; cout << "A++:" << A << endl; A--; cout << "A--:" << A << endl; cout << "++B:" << ++B << endl; cout << "--B:" << --B << endl; cout << "C:" << C << endl;*/ }
卡特兰数的应用还有很多,可以借鉴这个博客:https://blog.csdn.net/zuzhiang/article/details/77966726( 里面有关于其在一些题目的应用 )
附上求卡特兰常数的模板:
const int C_maxn = 1e4 + 10; LL CatalanNum[C_maxn]; LL inv[C_maxn]; inline void Catalan_Mod(int N, LL mod) { inv[1] = 1; for(int i=2; i<=N+1; i++)///线性预处理 1 ~ N 关于 mod 的逆元 inv[i] = (mod - mod / i) * inv[mod % i] % mod; CatalanNum[0] = CatalanNum[1] = 1; for(int i=2; i<=N; i++) CatalanNum[i] = CatalanNum[i-1] * (4 * i - 2) %mod * inv[i+1] %mod; }
参考博客:http://www.cnblogs.com/Rubbishes/p/9468916.html
以上是关于hdu 1130How Many Trees?(卡特兰数)的主要内容,如果未能解决你的问题,请参考以下文章
『题解』Codeforces9D How many trees?