组合数学

发布时间 2023-12-21 19:08:18作者: viewoverlook

组合数学

概念

image.png

image.png

二项式定理

\[\begin{array}{l} (x+y)^{n} = \left(\begin{array}{cc} n \\ 0 \end{array} \right) x^{n}y^{0} + \left(\begin{array}{cc} n \\ 1 \end{array} \right) x^{n-1}y^{1}+ \left(\begin{array}{cc} n \\ 2 \end{array} \right) x^{n-2}y^{2} + \dots + \left(\begin{array}{cc} n \\ n \end{array} \right) x^{0}y^{n} \end{array} \]

\[(x+y)^{n} = \sum^{n}_{k=0} \left(\begin{array}{cc} n \\ k\end{array} \right)x^{n-k}y^{k}=\sum^{n}_{k=0} \left(\begin{array}{cc} n \\ k \end{array} \right)x^{k}y^{n-k} \]

恒等式

基本恒等式:

\[\begin{array}{l} k *C^{k}_{n} = n*C^{k-1}_{n-1} \\ C^{n}_{k} * C^{k}_{m} = C^{n}_{m} * C^{m - k}_{m - n} (m-k < m-n) \\ \sum^{n}_{i=0}C^{i}_{n} = 2^{n} \\ \sum^{n}_{k=0}(-1)^{k}*C(k,n) = 0 \\ C^{k}_{n} + C^{k+1}_{n} = C^{k+1}_{n+1} \\ \sum^{n}_{l=0}C^{k}_{l} = C^{k+1}_{n+1} \tag{1.1} \end{array} \]

组合应用

求幂和:

\[\begin{array}{l} \sum{i^{2}} = \sum{i(i-1)}+\sum{i} \\ =2\sum{C(2,i)}+\sum{C(1,i)} \\ =2C(3,n+1)+C(2,n+1) \\ =\frac{(n+1)n(n-1)}{3}+\frac{(n+1)n}{2} \\ =\frac{n(n+1)(2*n+1)}{6} \\ \sum{i^{3}}=\sum{(i+1)i(i-1)}+\sum{i} \\ = 6\sum{C(3, i+1)}+\sum{C(1,i)} \\ =6C(4,n+2)+ C(2,n+1)\\ =\frac{(n+2)(n+1)n(n-1)}{4} + \frac{(n+1)n}{2} \\ =[\frac{n(n+1)}{2}]^2 \end{array} \]

image.png

image.png

image.png

image.png

#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <array>
using namespace std;
#define x first
#define y second
typedef pair<int, int> PII;
typedef long long LL;
const int N = 2010;
int k, n, p;
LL comb[N][N], inv[N], s[N];
int main()
{	
	scanf("%d%d%d",&k,&n,&p);
	// 杨辉三角
	for(int i = 0; i <= k + 1; i++)
	{
		comb[i][0] = comb[i][i] = 1;
		for(int j = 1; j < i; j++)
		{
			comb[i][j] = (comb[i-1][j-1] + comb[i-1][j]) % p;
		}
	}
	//逆元
	inv[1] = 1;
	for(int i = 2; i <= k + 1; i++)
	{
		inv[i] = (p - p / i) * inv[p % i] % p;
	}
	LL pw = 1;
	s[0] = n;
	for(int i = 1; i <= k; i++)
	{
		pw = pw * (n + 1) % p;
		s[i] = (pw - 1);
		for(int j = 0; j < i; j++)
		{
			s[i] = (s[i] - s[j] * comb[i+1][j]) % p;
		}
		s[i] = s[i] * inv[i+1] % p;
	}
	if(s[k] < 0) s[k] += p;
	printf("%lld\n", s[k]);

	return 0;
}