用c++实现Catalan数列、伯努利错装信封问题

4.2.2 Catalan数列

【问题】Catalan数列是欧拉在计算凸多边形的三角形剖分问题时得到的。在一个凸n(n>=3)边形中,通过插入内部不相交对角线将其剖分成一些三角形区域,问有多少种不同的分法?三角形只有一种剖分方法,图4-1所示是四边形的两种剖分,图4-2所示是五边形的5种剖分。Catalan数列的前5项是{1, 2, 5, 14, 42,...}


【想法】 由几何学知识,当n二4时,凸n边形的一个剖分需引n-3条互不相交的对角线,将内部区域剖分成n-2个三角形。凸n边形的顶点用A1, A2, …,An 表示,取边A1,An, 再取凸n边形的
任一个顶点Ak(2<=k<=n-1), 将Ak分别与A1和An连线得到三角形T,则三角形T将凸n边形分成R1、T和R2三个部分,其中R1为凸k边形,R2为凸n-k+1边形,如图4-3所示。

令h(n)表示凸n边形的三角形剖分方案数,则R1有h(k)种剖分方法,R2有h(n-k+1)种剖分方法。补充定义h(2)=1, 得到 Catalan 数列的递推关系式:


【算法实现】 设函数 Catalan 求解 Catalan 数列,设数组c[n+1]存储n个 Catalan 数列,补充赋值c[o]=c[1]=0,程序如下。

#include <iostream>
using namespace std;


int Catalan(int n) {
    if (n <= 1) {
        return 1;
    } else {
        int result = 0;
        for (int i = 0; i < n; i++) {
            result += Catalan(i) * Catalan(n - i - 1);
        }
        return result;
    }
}
int main( )
{
 int n;
    std::cout << "请输入 Catalan 数列的索引:";
    std::cin >> n;

    int catalanNumber = Catalan(n);
    std::cout << "索引 " << n << " 的 Catalan 数为:" << catalanNumber << std::endl;

    return 0;
}

【算法分析】两数Catalan由两层嵌套循环构成,基本语句”temp +=c*[k]*c[i-k+1];"
的执行次数是


 


4.3.1 伯努利错装信封问题


【问题】欧洲数学家伯努利收到一位朋友的来信,打开一看信不是写给他的,但是信封上的地址、姓名都没有问题。过了几天,他收到这位朋友的道歉信,解释说:写了5封信,又写好了5个信封,然后让仆人把信寄出,可是那位仆人在把信装到信封里时居然全部都装错了!看完信后伯努利不禁哈哈大笑。不过他马上想到了一个问题:5 封信装入写有不同地址和姓名的5个信封,全部装错的可能性有多少种?
【想法】 伯努利错装信封问题又称错排问题(error permutation problem)。假设有n个信封,依次编号为1、2.…n,有n封信,也依次编号为1、2、….n,则编号i(1<=i<=n)的信只有装入编号i的信封才是正确的。设Fn表示n错排问题,有F1=0, F2=1。当n>2时,设第一封信装在第二个信封中,若第二封信装在第一个信封中,则剩下的即为n-2错排问题;若第二封信不装在第一个信封中,则剩下的即n-1错排问题,设第一封信不装在第一个信封中,共有n-1种方法,得到如下递推关系式:



【算法实现】 设函数 Bernoulli 实现错排问题,变量b1和b2分别存储n-1和n-2错排数,程序如下。

#include <iostream>
using namespace std;


/**
 * 计算 Bernoulli 数的函数
 * 
 * @param n 要计算的 Bernoulli 数的索引
 * @return 索引为 n 的 Bernoulli 数
 */

int Bernoulli(int n)
{
int i, b, b1 = 1, b2 = 0;
for (i = 3; i <= n; i++)
{
b = (i - 1) * (b1 + b2); b2 = b1; b1 = b;
}
return b;
}


int main() {
    int n;
    cout << "请输入一个大于 2 的正整数:"; // 请求用户输入
    cin >> n;

    if (n < 3) { // 修改:添加错误处理
        cout << "输入应为大于 2 的正整数" << endl;
        return 1;
    }

    int bernoulliNumber = Bernoulli(n); // 计算并存储 Bernoulli 数
    cout << "索引为 " << n << " 的 Bernoulli 数为:" << bernoulliNumber << endl; // 输出 Bernoulli 数

    return 0;
}

【算法分析】 显然,算法Bernoulli的时间复杂度为O(n)。

  • 29
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值