zoukankan      html  css  js  c++  java
  • 卡特兰数

    卡特兰数是一种经典的组合数,前几项为:

    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)=C(2n,n)/(n+1)

    令h(0)=1,h(1)=1;

    卡特兰数的递推式:h(n)= h(0)*h(n-1) + h(1)*h(n-2) + ... + h(n-1)h(0) (n>=2)。

    //35以内的卡特兰数
    void init() {
        long long h[36];
        h[0] = h[1] = 1;
        for (int i = 2; i < 36; i++) {
            h[i] = 0;
            for (int j = 0; j < i; j++)
            h[i] = h[i] + h[j] * h[i - j - 1];
        }
    }

    大于35时,求h(n)%p,用卢卡斯定理

    h(n) % p = (Lucas(2n, n, p) - Lucas(2n, n - 1, p) + p) % p

    ll exp_mod(ll a, ll b, ll p) {
        ll res = 1;
        while (b) {
            if (b & 1) res = (res * a) % p;
            a = (a * a) % p;
            b >>= 1;
        }
        return res;
    }
    ll comb(ll a, ll b, ll c) {
        if (a < b) return 0;
        if (a == b) return 1;
        if (b > a - b) b = a - b;
        ll ans = 1, ca = 1, cb = 1;
        for (ll i = 0; i < b; i++) {
            ca = (ca * (a - i)) % p;
            cb = (cb * (b - i)) % p;
        }
        ans = (ca * exp_mod(cb, p - 2, p)) % p;
        return ans;
    }
    ll lucas(ll n, ll m, ll p) {
        //Lucas求C(n,m)
        ll ans = 1;
        while (n && m && ans) {
            ans = (ans * comb(n % p, m % p, p)) % p;
            n /= p;
            m /= p;
        }
        return ans;
    }

    求卡特兰大数

    int a[101][101], b[101];
    //b[i]保存的是第i位卡特兰数的长度
    //a[i]数组保存的是第i位卡特兰数的数值,高位存高位,低位存低位
    void catalan() {
        int len, carry, temp;
        a[1][0] = b[1] = 1;
        len = 1;
        for (int i = 2; i <= 100; i++) {
            for (int j = 0; j < len; j++)
                a[i][j] = a[i - 1][j] * (4 * (i - 1) + 2);
            carry = 0;
            for (int j = 0; j < len; j++) {
                temp = a[i][j] + carry;
                a[i][j] = temp % 10;
                carry = temp / 10;
            }
            while (carry) {
                a[i][len++] = carry % 10;
                carry /= 10;
            }
            carry = 0;
            for (int j = len - 1; j >= 0; j--) {
                temp = carry * 10 + a[i][j];
                a[i][j] = temp / (i + 1);
                carry = temp % (i + 1);
            }
            while (!a[i][len - 1]) len--;
            b[i] = len;
        }
    }
    #include <iostream>
    using namespace std;
    int a[105][100];
    int main( ) {
        int n,len;
        memset(a,0,sizeof(a));
        a[1][1]=1;
        a[1][0]=1; //a[n][0] 保存长度
        a[2][1]=2;
        a[2][0]=1;
        len=1;
        for(int i=3; i<=100; i++) {
            int yu(0),t;
            for(int j=1; j<=len; j++) { //乘的模拟
                t=(a[i-1][j])*(4*i-2)+yu;
                a[i][j]=t%10;
                yu=t/10;
            }
            while(yu) {
                a[i][++len]=yu%10;
                yu/=10;
            }
            for(int j=len; j>=1; j--) {  //除的模拟
                t=a[i][j]+yu*10;
                a[i][j]=t/(i+1);
                yu=t%(i+1);
            }
            while(!a[i][len]) len--;
            a[i][0]=len;
        }
        while(cin>>n) {
            for(int i=a[n][0]; i>0; i--)
            cout<<a[n][i];
            cout<<endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    hive与hbase整合
    待重写
    hive DML
    【知识强化】第六章 总线 6.1 总线概述
    【知识强化】第五章 中央处理器 5.1 CPU的功能和基本结构
    【知识强化】第四章 指令系统 4.3 CISC和RISC的基本概念
    【知识强化】第四章 指令系统 4.2 指令寻址方式
    【知识强化】第四章 指令系统 4.1 指令格式
    【知识强化】第三章 存储系统 3.6 高速缓冲存储器
    【知识强化】第三章 存储系统 3.5 双口RAM和多模块存储器
  • 原文地址:https://www.cnblogs.com/iwomeng/p/11354794.html
Copyright © 2011-2022 走看看