推荐阅读 NOIp 基础数论知识点总结: https://www.cnblogs.com/greyqz/p/number.html
排列组合
常用公式
排列:$$displaystyle A_n^m=frac{n!}{(n-m)!}$$
全排列:(A_n^n=n!)
组合:$$displaystyle C_nm=frac{A_nm}{m!}=frac{n!}{m!(n-m)!}$$
组合数的性质:
推导:$$ displaystyle egin{aligned} C_n^m & = frac{n!}{m!(n-m)!} & = frac{(n-1)!}{m!(n-m-1)!} imesfrac{n}{n-m} & =frac{(n-1)!}{m!(n-m-1)!} imes(1+frac{m}{n-m}) & =C_{n-1}^{m}+frac{(n-1)!}{(m-1)!(n-m)!} & = C_{n-1}m+C_{n-1}{m-1}end{aligned} $$
二项式定理:$$displaystyle (a+b)n=sum_{i=0}n C_n^i a^i b^{n-i}$$
组合数基本处理 (O(n))
const int N = 1e5 + 7, MOD = 1e9 + 7;
int add(int a, int b) { if ((a += b) >= MOD) a -= MOD; return a; }
int mul(int a, int b) { return ll(a) * b % MOD; }
int C(int a, int b) { return mul(jc[a], mul(ijc[a - b], ijc[b])); }
int qpow(int a, int b) {
int r = 1;
for (; b; b >>= 1) {
if (b & 1) r = mul(r, a);
a = mul(a, a);
}
return a;
}
int jc[N], ijc[N];
void ini() {
jc[0] = 1; for (int i = 1; i < N; i++) jc[i] = mul(jc[i - 1], i);
ijc[N - 1] = qpow(jc[N - 1], MOD - 2);
for (int i = N - 2; i >= 0; i--) ijc[i] = mul(ijc[i + 1], i + 1);
}
Lucas 定理
对于正整数 (n, m~ (nge m)), 素数 (p), 令 (n=n_kp_k+n_{k-1}p^{k-1}+cdots+n_1p+n_0), (m=m_kp_k+m_{k-1}p^{k-1}+cdots+m_1p+m_0), 则
可变形为:
用 Lucas 定理可快速求解 (C_n^mmod p). 代码:
const int mod=10007;
int jc[mod], ijc[mod], T, n, m;
inline int lucas(int a, int b) {
if (a>b) return 0;
if (b<=mod) return jc[b]*ijc[a]%mod*ijc[b-a]%mod;
return lucas(a/mod, b/mod)*lucas(a%mod, b%mod)%mod;
}
int main() {
jc[0]=jc[1]=ijc[0]=ijc[1]=1;
for (int i=2; i<mod; ++i)
jc[i]=jc[i-1]*i%mod, ijc[i]=(mod-mod/i)*ijc[mod%i]%mod;
for (int i=2; i<mod; ++i)
ijc[i]=ijc[i-1]*ijc[i]%mod;
for (scanf("%d", &T); T; --T)
scanf("%d%d", &n, &m), printf("%d
", lucas(m, n));
return 0;
}
矩阵乘法
由 (a_n=2a_{n-3}+a_{n-1}) 得矩阵转移方程:
这里采用 []
表示 (1 imes 3) 矩阵,()
表示 (3 imes 3) 矩阵。
ll p[5][5], b[5][5], d[5][5], t[5][5];
memset(p, 0, sizeof p), memset(b, 0, sizeof b), memset(d, 0, sizeof d);
for (int i=1; i<=3; i++) b[i][i]=1ll; // unit matrix
p[1][1]=1ll, p[1][2]=1ll, p[1][3]=0ll;
p[2][1]=0ll, p[2][2]=0ll, p[2][3]=1ll;
p[3][1]=2ll, p[3][2]=0ll, p[3][3]=0ll; // transition matrix
d[1][1]=6ll, d[1][2]=1ll, d[1][3]=3ll; // initial matrix, a_3, a_2, a_1
// n<=3 特判
if (n<=3) {printf("%d
", d[1][4-n]); return 0; }
// 矩阵快速幂
int K=n-3;
while (K>0){
if (K&1) {
// (b) *= (p)
memset(t, 0, sizeof t);
for (int i=1; i<=3; i++)
for (int j=1; j<=3; j++)
for (int k=1; k<=3; k++)
t[i][j]=(t[i][j]+b[i][k]*p[k][j]) % mod;
memcpy(b, t, sizeof b);
}
// (p) = (p)^2
memset(t, 0, sizeof t);
for (int i=1; i<=3; i++)
for (int j=1; j<=3; j++)
for (int k=1; k<=3; k++)
t[i][j]=(t[i][j]+p[i][k]*p[k][j]) % mod;
memcpy(p, t, sizeof p);
K>>=1;
}
// [t] = [d] * (b)
memset(t, 0, sizeof t);
for (int i=1; i<=3; i++)
for (int j=1; j<=3; j++)
t[1][i]=(t[1][i]+d[1][j]*b[j][i]) % mod;
printf("%lld
", t[1][1]);
数学规律
Catalan 数
1, 1, 2, 5, 14, 42, 132, ...
以下问题属于 Catalan 数:
- 有 (2n) 个人排成一行进入剧场. 入场费 5 元. 其中只有(n)个人有一张 5 元钞票, 另外 (n) 人只有 10 元钞票, 剧院无其它钞票, 问有多少中方法使得只要有 10 元的人买票, 售票处就有 5 元的钞票找零?
- 一位大城市的律师在她住所以北 (n) 个街区和以东 (n) 个街区处工作. 每天她走 (2n) 个街区去上班. 如果他从不穿越(但可以碰到)从家到办公室的对角线, 那么有多少条可能的道路?
- 在圆上选择 (2n) 个点, 将这些点成对连接起来使得所得到的 (n) 条线段不相交的方法数?
- 对角线不相交的情况下, 将一个凸多边形区域分成三角形区域的方法数?
- 一个栈 (无穷大) 的进栈序列为 (1,2,3, ldots ,n) 有多少个不同的出栈序列?
- (n) 个结点可够造多少个不同的二叉树?
- (n) 个不同的数依次进栈, 求不同的出栈结果的种数?
- (n) 个 (+1) 和 (n) 个 (-1) 构成 (2n) 项 (a_1,a_2, ldots ,a_{2n}), 其部分和满足 (a_1+a_2+ cdots +a_kge 0) ((k=1,2,3, ldots ,2n)), 该数列为?
ssoj1073:给定 (0<p<q<100,p,qinmathbf{N}^*), 求 (displaystylefrac{H_q}{H_p}).
解:令 (q=p+x,xinmathbf{N}^*), 则
[displaystyle frac{H_q}{H_p}=frac{C_{2q}^qcdot (p+1)}{C_{2p}^pcdot (q+1)} =frac{displaystylefrac{(2q)!}{(q!)^2}cdot (p+1)}{displaystylefrac{(2p)!}{(p!)^2}cdot (q+1)}=frac{displaystylefrac{(2p+2x)!}{ig((p+x)!ig)^2}cdot (p+1)}{displaystylefrac{(2p)!}{(p!)^2}cdot (p+x+1)}=frac{displaystyleprod_{i=2p+1}^{2q}{i}cdot(p+1)}{left(displaystyleprod_{i=p+1}^q{i} ight)^2 (q+1) } ]带入特殊值计算.
Stirling 数
(2007 普及)将 (n) 个数 (1,2,ldots,n) 分成 (r) 个部分. 每个部分至少一个数. 将不同划分方法的总数记为 (S_n^r). 例如, (S_4^2=7), 这 7 种不同的划分方法依次为 ({(1) , (234) },{(2) , (134) },{(3) , (124) },{ (4) , (123) },{ (12) , (34) },{ (13) , (24) },{ (14) , (23) }). 当 (n=6, r=3) 时, (S_6^3=)( )