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

原文地址:https://www.cnblogs.com/zhgyki/p/9581772.html

时间: 2024-10-11 10:04:17

hdu 1130How Many Trees?(卡特兰数)的相关文章

LA 5092 &amp;&amp; hdu 3723 Delta Wave (卡特兰数)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=3723 and http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=20568 题意:有种折线每向右延伸一个单位长度,高度要么不变,要么加1,要么减1.而且任何时刻高度不能低于0.求这种折线最终高度为0的情况总数. 分析:由于任何时刻斜向上的线不小于斜向下的线的数目,而且最终相等,,,,,卡特兰数模型.卡特兰数资料 若有i条斜向上的线,那

HDU 5673 Robot(卡特兰数)

题目链接:点击打开链接 思路:卡特兰数可以用来求括号序列的个数, 用了组合数学的知识. 该题其实就等价于求一个括号序列的个数, 因为满足任意时刻, 向右的步数大于等于向左的步数. 但是该题还有停止不动的情况, 所以我们不妨枚举向右的步数, 然后求出括号序列的组合数, 然后剩下的就是停止不动的步数, 用组合数插空即可. 另外, 除法取模要取逆元, 我们可以线性预处理出所有逆元. 细节参见代码: #include<cstdio> #include<cstring> #include&l

HDU 4828 Grids(卡特兰数+乘法逆元)

首先我按着我的理解说一下它为什么是卡特兰数,首先卡特兰数有一个很典型的应用就是求1~N个自然数出栈情况的种类数.而这里正好就对应了这种情况.我们要满足题目中给的条件,数字应该是从小到大放置的,1肯定在左上角,所以1入栈,这时候我们放2,如果我们把2放在了1的下面就代表了1出栈,把2放在上面就代表了2也进栈(可以看一下hint中第二组样例提示),以此类推,这样去放数,正好就对应了上面一行入栈,下面一行出栈的情况,一共n行,对应上限为n的卡特兰数. 需要注意的地方就是在使用卡特兰数递推式的时候,除法

FZU 1775 Counting Binary Trees 卡特兰数前n项和%m(m可为非素数

题目链接:点击打开链接 题意: 卡特兰数前n项和 结果%m 把答案当成2部分搞. #include<stdio.h> #include<cmath> #define int __int64 const int N = 100000; struct inverse_element{ int x, y, q; void extend_Eulid(int a,int b) { if(b == 0){ x = 1;y = 0;q = a; }else{ extend_Eulid(b,a%b

UVa 10007 &amp; hdu 1131 Count the Trees (卡特兰数)

Count the Trees Time Limit:3000MS    Memory Limit:0KB     64bit IO Format:%lld & %llu SubmitStatus Description  Count the Trees  Another common social inability is known as ACM (Abnormally Compulsive Meditation). This psychological disorder is somewh

【HDU 5370】 Tree Maker(卡特兰数+dp)

Tree Maker Problem Description Tree Lover loves trees crazily. One day he invents an interesting game which is named Tree Maker. In this game, all trees are binary trees. Initially, there is a tree with only one vertex and a cursor on it. Tree Lover

hdu 5177 (1e18范围的卡特兰数)

hdu 5177 (1e18范围的卡特兰数) 题意: 求第n个卡特兰数,模3814697265625 (5^18) 限制: 有20组数据,1 <= n <= 1e18 思路: 1. 卡特兰数的表达式: ans = 1/(n+1) * C(2*n,n) -> ans = 1/(n+1) * (2n)! / n! / n!    ---1式 2. 因为要模5^18,求逆元要求互质,所以先把"1式"中的因子5全部去掉 3. 然后看不含因子5的阶乘,f(n!) 4. 设g(x

hdu 4828 Grids(拓展欧几里得+卡特兰数)

题目链接:hdu 4828 Grids 题目大意:略. 解题思路:将上一行看成是入栈,下一行看成是出栈,那么执着的方案就是卡特兰数,用递推的方式求解. #include <cstdio> #include <cstring> typedef long long ll; const int N = 1000005; const ll MOD = 1e9+7; ll dp[N]; ll extendGcd(ll a, ll b, ll& x, ll& y) { if (

2014年百度之星程序设计大赛 - 初赛(第一轮) hdu Grids (卡特兰数 大数除法取余 扩展gcd)

题目链接 分析:打表以后就能发现时卡特兰数, 但是有除法取余. f[i] = f[i-1]*(4*i - 2)/(i+1); 看了一下网上的题解,照着题解写了下面的代码,不过还是不明白,为什么用扩展gcd, 不是用逆元吗.. 网上还有别人的解释,没看懂,贴一下: (a / b) % m = ( a % (m*b)) / b 笔者注:鉴于ACM题目特别喜欢M=1000000007,为质数: 当gcd(b,m) = 1, 有性质: (a/b)%m = (a*b^-1)%m, 其中b^-1是b模m的逆