• 卡特兰数


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

    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
  • 相关阅读:
    【读书笔记】房龙-人类的故事
    【读书笔记】曼昆-经济学原理:宏观经济学分册
    【读书笔记】曼昆-经济学原理:微观经济学分册
    ES6数组去重
    switch语句
    if语句的优化
    程序的三大结构
    NaN
    js中常见的数据类型
    变量的命名规则
  • 原文地址:https://www.cnblogs.com/iwomeng/p/11354794.html
Copyright © 2020-2023  润新知