组合计数学习笔记
本篇主要讲解组合计数块:快速幂、逆元、排列组合、Lucas定理、插板法、折线计数
1. 快速幂
快速幂是用来在 \(\mathcal{O}(\log{b})\) 的时间内求出 \({a^b}\bmod c\)。
采用分治思想,如果 \(b\) 为偶数,则 \(a^b=a^{\frac{b}2}\times a^{\frac{b}2}\),如果 \(b\) 为奇数 \(a^b=a^{\lfloor\frac{b}2\rfloor}\times a^{\lfloor\frac{b}2\rfloor}\times a\)。采用同样的思想分解 \(\frac{b}2\),可以在 \(\log{b}\) 时间复杂度的范围内求解出 \(a^b\)。
例:\(x^{20}={(x^4)}^5=x^4\times{(x^8)}^2=x^4\times{(x^{16})}^1\)。
代码:
inline int qpow(int a, int b, int mod){
int s = 1;
while (b) {
if (b & 1) s = (s * a) % mod;
a = (a * a) % mod;
b >>= 1;
}
return s % mod;
}
1.1 例题
I. P1226 【模板】快速幂
求 \(a^b\bmod{p}\)
// Problem: P1226 【模板】快速幂
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1226
// Memory Limit: 128 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
/*
author: Nimbunny
powered by c++14
*/
#include <bits/stdc++.h>
#define endl '\n'
#define pi pair<int, int>
#define int long long
// #pragma GCC optimize(2)
using namespace std;
const int N = 2e5 + 10;
int x, y, mod;
inline int qpow(int a, int b) {
int s = 1;
while (b) {
if (b & 1) s = (s * a) % mod;
a = (a * a) % mod;
b >>= 1;
}
return s % mod;
}
signed main() {
cin.tie(nullptr)->sync_with_stdio(false);
cin >> x >> y >> mod;
cout << x << "^" << y << " mod " << mod << "=" << qpow(x, y)
<< endl;
return 0;
}
II. P1965 [NOIP 2013 提高组] 转圈游戏
显然答案为 \((x+m\times10^k)\bmod n\)。
P1965
#include<bits/stdc++.h>
#define endl '\n'
#define int long long
//#define pi pair<int,int>
//#pragma GCC optimize(2)
using namespace std;
const int INF = INT_MAX;
const int mod = 1e9 + 7;
const int N = 1e5 + 10;
int n, m, k, x;
int qpow(int a, int b) {
int ans = 1;
while (b) {
if (b & 1) ans = (ans * a) % n;
a = (a * a) % n;
b >>= 1;
}
return ans % n;
}
signed main() {
cin.tie(nullptr)->sync_with_stdio(false);
cin >> n >> m >> k >> x;
cout << (x + m * qpow(10, k) % n) % n << endl;
return 0;
}
2. 逆元
模意义下乘法运算的逆元(Modular Multiplicative Inverse),如果一个线性同余方程 \(ax \equiv 1 \pmod{b}\),则 \(x\) 称为 \(a\bmod{b}\) 的逆元,记作 \(a^{-1}\)。
2.1 解法
3. 排列组合
排列组合是组合数学的基础,排列就是指从给定个数的元素中取出指定个数的元素进行排序,而组合则是指从给定个数的元素中仅仅取出指定个数的元素,不考虑排序。
排列组合的中心问题是研究给定要求的排列和组合可能出现的情况总数,排列组合与古典概率论关系密切。
1.1 加法与乘法原理
加法原理:
完成一件事可以有 \(n\) 种办法,\(a_i(1\le i\le n)\) 代表第 \(i\) 类方法的数目。那么完成这件事共有 \(S=a_1+a_2+\cdots+a_n\) 种不同的方法。
乘法原理:
完成一个工程需要分 \(n\) 个步骤,\(a_i(1\le i\le n)\) 代表第 \(i\) 个步骤的不同方法数目。那么完成这件事共有 \(S=a_1\times a_2\times\cdots\times a_n\) 种不同的方法。
1.2 排列数与组合数
排列数:
从 \(n\) 个不同的物品中按一定顺序选 \(m\) 个,叫做从 \(n\) 个不同物品中取出 \(m\) 个物品的排列数。
公式如下:\(\mathrm A_n^m=n(n-1)(n-2)\dots(n-m+1)=\frac{n!}{(n-m)!}\)。较为生动的理解:有 \(n\) 个人,\(m\) 个位置,第 \(1\) 个位置可以选 \(n\) 个人,第 \(2\) 个位置可以选 \(n-1\) 个人,……,第 \(m\) 个可以选 \(n-m+1\) 个人。
组合数:
从 \(n\) 个不同的物品中,任取(没有顺序),叫做从 \(n\) 个不同物品中取出 \(m\) 个元素的一个组合,用 \(\dbinom nm\) 来表示,读作 \(\lceil n\) 选 \(m\rfloor\)。
组合数计算公式:
生动的解释:考虑 \(n\) 个人选 \(m\) 个出来(\(m\le n\)),不排队,不在乎顺序。如果在乎顺序那么就是 \(\mathrm A_n^m\),如果不在乎那么就要除掉重复,那么重复了多少?同样选出来的 \(m\) 个人,他们还要 \(\lceil\) 全排 \(\rfloor\) 得 \(m!\)。
tips:现在数学界普遍采用 \(\dbinom{n}{m}\) 的记号而非 \(\mathrm C_n^m\)。
组合数也被称为 \(\lceil\) 二项式系数 \(\rfloor\),下文二项式定理将会阐述其中的联系。
插板法
插板法是用来求给相同元素分组的方案数的一种方法,也可以用于求一类线性不定方程的解的组数。
正整数和的数目
问题:现有 \(n\) 个 完全相同 的物品,要求将其分为 \(k\) 组(每组至少一个),一共有多少种分法?

共 \(8\) 个物品,分为 \(k\) 组,每组至少一个。假设我们有 \(k-1\) 个板子,用来插到标记为绿色的地方,共 \(8-1=7\) 个位置,我们可以在 \(7\) 个位置中任选 \(k-1\) 个位置插入 \(k-1\) 个板,因为每组无差别,所以数目为 \(\dbinom{n-1}{k-1}\)。
非负整数和的数目
问题:现有 \(n\) 个 完全相同 的物品,要求将其分为 \(k\) 组(每组可以为空),一共有多少种分法?
直觉告诉我,要转化一下。具体的,就是多个板塞在同一个缝隙中是允许的,毛估估有点难算。但是可以将每组提前分配一个物品,

浙公网安备 33010602011771号