-
从有限集合A={a1, a2, …, an}上选取r个元素排成一个环形,这样的排列称为A的一个r-环排列。
-
由n个元素组成的集合A的r-环排列数是:
-
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的重数。若有限多重集S有a1, a2, …, ak共k个不同元素,且ai的重数为ni,则S可记为:{ n1•a1, n2•a2, ……, nk•ak }。
-
多重集的排列数与组合数_diviner_s的博客-CSDN博客
隔板法解某些方程问题:
组合数学_排列与组合_c84排列组合怎么计算_diviner_s的博客-CSDN博客
鸽笼原理:
例题:
-
一个国际象棋选手为参加国际比赛,突击训练77天,要求每天至少下一盘棋,每周至多下12盘棋。
-
证明:无论如何安排总可以使他在这77天里有连续几天共下21盘棋。
错位排列: