九月二号学习笔记(组合数)排列和组合一定要区分开

  • 从有限集合A={a1, a2, …, an}上选取r个元素排成一个环形,这样的排列称为A的一个r-环排列

  • n个元素组成的集合Ar-环排列数是:

  • P(n, r)/r

  • 4.2.1.6  1, 2, , 300之中任取3个数,使得它们的和能被3整除,有多少种选取方法?

杨辉三角定理:

  • C(n+1, k)=C(n, k)+C(n, k-1)

二项式系数的公式:

插入一个小插曲:产生随机数。

#include <iostream>
#include <random>
#include<bits/stdc++.h>
using namespace std;

int main()
{
    //std::mt19937 rng(std::random_device{}());
    //std::mt19937 mt_rand(std::random_device{}());
    //std::mt19937 rng(time(0));
    std::mt19937 rng(std::chrono::system_clock::now().time_since_epoch().count());
    for (int i = 0; i < 5; i++) {
        cout << rng() << endl;
    }

    return 0;
}
 

卡特兰数问题:

经典问题:「算法入门笔记」卡特兰数 - 知乎 (zhihu.com)

计算方法:

卡特兰数又称卡塔兰数,卡特兰数是组合数学中一个常出现在各种计数问题中的数列。以比利时的数学家欧仁·查理·卡塔兰 (1814–1894)的名字来命名。但最早是欧拉在1753年解决凸包划分成三角形问题的时候,推出的Catalan数。

初始值:f(0) = f(1) = 1
递推公式:f(n) = f(0) * f(n - 1) + f(1) * f(n - 2) + …… + f(n - 1) * f(0)
————————————————
版权声明:本文为CSDN博主「SkeletonKing233」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/SkeletonKing233/article/details/102649964

# include <cstdio>
# include <iostream>
# include <cmath>
# include <cstring>
# include <algorithm>
# include <climits>

using namespace std;

# define FOR(i, a, b) for(int i = a; i <= b; i++)
# define _FOR(i, a, b) for(int i = a; i >= b; i--)

const int NR = 100000;

int n;
long long catalan[NR + 10];

int main()
{
	scanf("%d", &n);
	catalan[0] = catalan[1] = 1;
	FOR(i, 2, n)
		FOR(j, 0, i - 1)
			catalan[i] += catalan[j] * catalan[i - j - 1];
	for(int i=1;i<=n;i++)
	{
		cout<<i<<" "<<catalan[i]<<endl;
	}
	return 0;
}

总结:

进出栈匹配,括号匹配括号序列,n+1个节点的二叉树的个数问题,买票问题,等等都可以用卡特兰数解决。

无序的情况下是卡特兰数的组合问题,有序的情况下是卡特兰数的排列问题。

就是在一些步骤之前,使得+1数量大于等于-1数量的组合问题。

例如:括号序列就是  在某一个点上,‘(’的数量应该大于‘)’的数量,此时的组合数就是卡特兰数。 进出栈也是同样的道理,在任意一个时刻,进栈的数量应该远远大于出栈的数量。

贝尔数:

贝尔数是以埃里克·坦普尔·贝尔命名,是组合数学中的一组整数数列,开首是(OEIS的A000110数列):

B0=1,B1=1,B2=2,B3=5,B4=15,B5=52,B6=203,...

Bn的含义是基数为 n 的集合划分成非空集合的划分数。

例如, B3=5 是因为3个元素的集合有5种划分方法:

{{a}, {b}, {c}}
{{a}, {b, c}}
{{b}, {a, c}}
{{c}, {a, b}}
{{a, b, c}};

贝尔三角形:

const int maxn = 2000 + 5;
int bell[maxn][maxn];

void f(int n) {
  bell[0][0] = 1;
  for (int i = 1; i <= n; i++) {
    bell[i][0] = bell[i - 1][i - 1];
    for (int j = 1; j <= i; j++)
      bell[i][j] = bell[i - 1][j - 1] + bell[i][j - 1];
  }
}

利用贝尔三角形求bell数:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 2000+5;
const int mod = 3;      //周期为13
int bell[maxn], T[maxn];

void Bell(int n, int mod)     //求前n项Bell数
{
    bell[0] = bell[1] = 1;
    T[0] = 1;T[1] = 2;
    for(int i = 2;i <= n;i++)
    {
        T[i-1] = bell[i-1];
        for(int j = i-2;j >= 0;j--)  //滚动数组
            T[j] = (T[j] + T[j+1]) % mod;
        bell[i] = T[0];
    }
}

int main()
{
    Bell(2000, mod);
    for(int i = 0;i < 100;i++)
        printf("%d%c", bell[i], (i+1)%13 == 0 ? '\n' : ' ');
}

斯特林数:

把n个不同的元素分配到k个圆排列里面,圆不能为空有多少种分发。(第一类问题)

把n个不同的球分配到k个相同的盒子里面,不能有空盒子。(第二类问题)

  •   多重集 的组合和排列问题:

  • 多重集是可重复出现的元素组成的集合。若多重集中不同元素个数为k,称该多重集为k元多重集。多重集中元素ai出现的次数ni称为元素ai的重数。若有限多重集Sa1, a2, …, akk个不同元素,且ai的重数为ni,则S可记为:{ n1•a1, n2•a2, ……, nk•ak }

多重集的排列数与组合数_diviner_s的博客-CSDN博客

隔板法解某些方程问题:

组合数学_排列与组合_c84排列组合怎么计算_diviner_s的博客-CSDN博客

鸽笼原理:

例题:

  • 一个国际象棋选手为参加国际比赛,突击训练77天,要求每天至少下一盘棋,每周至多下12盘棋。

  • 证明:无论如何安排总可以使他在这77天里有连续几天共下21盘棋。

错位排列:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值