数学章节总结

建议在洛谷上观看

质数

筛法

  • 暴力筛

    直接对于每一个数进行是否为质数,用一个bool函数即可
    代码如下:

inline bool prime(int n){                     
    if(n<=2)return false;                      
    for(int i=2;i*i<=n;i++)               
        if(n%i==0)return false;                  
    return true;                      
}               

时间复杂度: O($N\sqrt{N} $)

  • 埃氏筛(Eratosthenes)

    其算法思路为对于任意整数x的倍数2x、3x、4x......必然不是质数,依据此性质,我们可以从2开始枚举,并在每次枚举中只要这个数的倍数不超过n即可一直对其枚举标记。
    代码如下:

inline void primes(int n){                     
    memset(v,0,sizeof v);                 
    for(int i=2;i<=n;i++){                    
        if(v[i])continue;                     
        cout<<i<<'\n';                       
        for(int j=i;j*i<=n;j++)                 
            v[i*j]=1;                         
    }                                       
}                                           

时间复杂度: O(\(NloglogN\))

  • 线性筛法

    当我们在使用埃氏筛的时候,会发现一个消耗时间的问题,举个例子:在标记合数时,6会被3与2反复标记,从此,线性筛法诞生了!
    线性筛法通过“从大到小累积质因子”用3个步骤维护v
    1.依次考虑2到N之间的每一个数i
    2.若v[i]=0,说明i为质数
    3.扫描不大于v[i]的每个质数p,令v[i*p]=p
    代码如下:

void pri(int n){
    int m=0;
    for(int i=2;i<=n;i++){
        if(v[i]==0){
            v[i]=i;
            p[++m]=i;
        }
        for(int j=1;j<=m;j++){
            if(p[j]>v[i] || p[j]>n/i)break;
            v[i*p[j]]=p[j];
        }
    }
}

时间复杂度:O(N)

质因数分解

任何一个大于1的整数都能唯一分解为有限个质数的乘积可写作:
\(N=p_1^{C1} p_2^{C2} p_3^{C3}···p_m^{Cm}\)
所以结合试除法与埃氏筛法,我们可以扫描2到\(\sqrt N\) 的每一个数d,若d能整除N,则从N中除掉所有因子d,同时累计除去的d的个数。

void divide(int n){
	m=0;
	for(int i=2;i*i<=n){
		if(n%i==0){
			p[++m]=i;
			c[m]=0;
			while(n%i==0)n/=i,c[m]++;
		}
	}
	if(n>1)
		p[++m]=n,c[m]=1;
	for(int i=1;i<=m;i++)
		cout<<p[i]<<'^'<<c[i]<<'\n';	
} 

约数

约数基本定理

一个大于1的整数的正约数集合可以记作:

$\quad\left{p_{1}^{b_{1}} p_{2}^{b_{2}} \ldots p_{m}^{b_{m}}\right} \text{其中}0 \leqslant b_{i} \leqslant c_{i} $

其正约数个数可以记作:

$\prod_{i=1}^{m}\left(C_{i}+1\right) $
即每个\(C_i+1\)的乘积

其正约数之和可以记作:

\(\quad\left(1+p_{1}+p_{1}^{2}+\cdots+p_{1}^{c_{1}}\right) \cdots\left(1+p_{m}^{1}+p_{m}^{2}+\cdots+p_{m}^{cm}\right)=\prod_{i=1}^{m}\left(\sum_{j=0}^{c_{i}}\left(p_{i}\right)^{j}\right)\)

阶乘中因子出现的次数有

\(\left\lfloor\frac{n}{x}\right\rfloor+\left\lfloor\frac{n}{x^{2}}\right\rfloor+\left\lfloor\frac{n}{x^{3}}\right\rfloor+\ldots+\left\lfloor\frac{n}{x^{m}}\right\rfloor \text { 次。 }\)

(约数个数)代码:

#include<bits/stdc++.h>
using namespace std;
int n,sum;
int v[1000005];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++) for(int j=1;i*j<=n;j++)	v[i*j]++;	//当改成v[i*j]+=i时就是求约数和	
	for(int i=1;i<=n;i++)cout<<v[i]<<"\n";
	return 0;
} 

最大公约数

附:__gcd(int,int)是一个好用的函数(用于求int与int之间的最大公约数)

定义

最大公约数:对于一个数x,使它既为a的约数,也为b的约数,并使x尽可能地大。则x就是a,b的最大公约数
最小公倍数:对于一个数x,使它既为a的倍数,也为b的倍数,并使x尽可能地小。则x就是a,b的最小公倍数

性质(最大公约数)

设x为a,b的最大公约数,则有\(x \mid a\)\(x \mid b\),所以\(x \mid a-b\)

求解方法

由性质可以得出$gcd(a,b)=gcd(b,a - b )(a>b) \(。所以易得\)gcd(a,b)=gcd(b,a\bmod b)$

code:

int gcd(int a,int b){
    if(b==0) return a;
    return gcd(b,a%b);
}

欧拉函数

欧拉函数的定义 $ n 中与 n 互质的数的个数称为欧拉函数,记为 \varphi(n) 例: \varphi(1)=1, \varphi(2)=1, \varphi(3)=2, \varphi(4)=2, \varphi(5)=4 \( \)
欧拉函数的性质 $
$
1.若 p 是质数,则 \varphi(\mathrm{p})=\mathrm{p}-1 $
$2.若 p 是质数,则 \varphi\left(\mathrm{p}^{\mathrm{k}}\right)=(\mathrm{p}-1) \mathrm{p}^{\mathrm{k}-1} $
$3.积性函数:若 \operatorname{gcd}(\mathrm{m}, \mathrm{n})=1 ,则 \varphi(\mathrm{mn})=\varphi(\mathrm{m}) \varphi(\mathrm{n}) $
\(N=p_{1}^{c_{1}} p_{2}^{c_{2}} \ldots p_{m}^{c_{m}}\)
\(\varphi(N)=N \times\left(1-\frac{1}{p_{1}}\right)\left(1-\frac{1}{p_{2}}\right) \ldots\left(1-\frac{1}{p_{m}}\right)\)

费马小定理

设p是素数。对于任意整数a且\(p \nmid a\),都成立\(a^p ≡ a (mod p)\)

欧拉定理

若正整数 $ \mathrm{a}, \mathrm{n} 互质,则 a^{\varphi(n)} \equiv 1(\bmod n) ,其中 \varphi(\mathrm{n}) $ 为欧拉函数

扩展欧拉定理

若正整数 n 为质数,则对于任意整数 a 有$ a^{n} \equiv a(\bmod n) $

若正整数 \(\mathrm{a}, \mathrm{n} 互质,对于任意正整数 b ,则 a^{b} \equiv a^{b \bmod \varphi(n)}(\bmod n)\)

\(\begin{array}{c} b=q \times \varphi(n)+r \\ r=b \bmod \varphi(n) \end{array}\)

\(a^{b} \equiv a^{q \times \varphi(n)+r} \equiv\left(\underline{a}^{\varphi(\mathrm{n})}\right)^{q} \times a^{r} \equiv 1^{q} \times a^{r} \equiv a^{r} \equiv a^{b \bmod \varphi(n)}(\bmod \mathrm{n})\)

则 $a^{b} \equiv a^{b \bmod \varphi(n)+\varphi(n)}(\bmod n) $

裴蜀定理(又称贝祖定理)

定义

对于任意整数a,b,一定存在整数x,y满足\(ax+by=gcd(a,b)\)

则二元整数线性不定方程 ax+by=c 有解当且仅当\(gcd(a,b) \mid c\)

裴蜀定理求不定方程

问题:求 a x+b y=g c e l(a, b)- 组整数解
当 b=0 时 a x+b y=a ,故而 x=1, y=0
当$ b \neq 0 $ 时由欧几里得算法, $\operatorname{gcd}(a, b)=\operatorname{gcd}(b, a % b) $
由裴蜀定理 $\operatorname{gcd}(a, b)=a x+b y $
$\begin{array}{c}
\operatorname{gcdl}(b, a % b)=b x_{1}+(a % b) y_{1} \\
\quad=b x_{1}+\left(a-\left\lfloor\frac{a}{b}\right\rfloor \times b\right) y_{1} \\
\quad=a y_{1}+b\left(x_{1}-\frac{a}{b} y_{1}\right)
\end{array} \text { 所以, } {x=y_{1}, y=x_{1}-\frac{a}{b} y_{1}} \text {. } $

可以用递归算法,先求出下一层的 $\mathrm{x} 1, \mathrm{y} 1 $再回代到上一层,层层回代,可求特解 $ \left(\mathrm{x}{0}, \mathrm{y}\right) $构造通解

\(\begin{array}{c} x=x_{0}+\frac{b}{\operatorname{gcd}(a, b)} \times k \\\\ y=y_{0}+\frac{a}{\operatorname{gcdl}(a, b)} \times k \end{array}\)

矩阵

定义

一个 n * m 的矩阵可看作一个 n * m 的二维数组。矩阵的加法和减法就是把两个矩阵对应位置上的数相加减,即 $ C=A \pm B \Leftrightarrow \forall i \in[1, n], \forall j \in[1, m], C_{i, j}=A_{i, j} \pm B_{i, j} $ ,其中 A, B, C 都是 n * m 矩阵。

矩阵乘法

\(~~~~\) 矩阵乘法的定义略微复杂一些。设 A 是 n * m 矩阵, B 是 m * p 矩阵,则 C= A * B 是 n * p 矩阵,并且 $ \forall i \in[1, n], \forall j \in[1, p] : C_{i, j}=\sum_{k=1}^{m} A_{i, k} * B_{k, j} $ 也就是说,参与矩阵乘法运算的第一个矩阵的列数必须等于第二个矩阵的行数,所得到的结果矩阵的行数,列数分别等于第一个矩阵的行数,第二个矩阵的列数。结果矩阵 C 第 i 行第 j 列的数,是由 A 的第 i 行的 m 个数与 B 的第 j 列的 m 个数分别相乘再相加得到的。
\(~~~~\)矩阵乘法满足结合律,即 $ (A * B) * C=A *(B * C) $ ,满足分配律,即 (A+B) * C= A * C+B * C ,不满足交换律,即 A * B 不一定等于 B * A 。
\(~~~~\)考虑矩阵乘法中一种特殊的情形, F 是 1 * n 矩阵, A 是 n * n 矩阵,则 $ F^{\prime}=F * A $ 也是 $1 * n $ 矩阵。 F 和 $ F^{\prime} $ 可看作一维数组,省略它们的行下标 1。按照矩阵乘法的定义,$ \forall j \in[1, n] $ ,有 $ F_{j}{\prime}=\sum_{k=1} F_{k} * A_{k, j} $ 。它的含义是,经过一次与 A 的矩阵乘法运算后, F 数组中的第 k 个值会以 $ A_{k, j} $ 为系数累加到 F^{\prime} 数组的第 j 个值上,等价于在一个向量的 k, j 两个状态之间发生了递推。

#include<bits/stdc++.h>
#define int long long 
using namespace std;
const int M=1e4;
int n,k;
struct matrict{
	int a[5][5];
	matrict(){
		memset(a,0,sizeof a);
	}
};
matrict operator *(matrict A,matrict B){
	matrict c;
	for(int i=1;i<=2;i++){
		for(int j=1;j<=2;j++){
			for(int x=1;x<=2;x++){
				c.a[i][j]=(c.a[i][j]+A.a[i][x]*B.a[x][j])%M;
			}
		}
	}
	return c;
}

signed main(){
	while(cin>>n && n!=-1){
        if(n==0 || n==1){
            cout<<n<<'\n';
            continue;
        }
        matrict a,ans;
        a.a[1][1]=a.a[1][2]=a.a[2][1]=1;
        for(int i=1;i<=2;i++){
            ans.a[i][i]=1;
        }
        int k=n-2;
        while(k){
            if(k&1)ans=ans*a;
            a=a*a;
            k>>=1;
        }
        cout<<(ans.a[1][1]+ans.a[1][2])%M<<'\n';
    }
	return 0;
}

单位矩阵

定义:对角线为1,其余部分为0的n*n的矩阵叫做单位矩阵。
性质:任意能与他相乘的矩阵与他相乘后都会回到本身。

高斯消元

定义

消元法是将方程组中的一方程的未知数用含有另一未知数的代数式表示,并将其带入到另一方程中,这就消去了一未知数,得到一解;或将方程组中的一方程倍乘某个常数加到另外一方程中去,也可达到消去一未知数的目的。消元法主要用于二元一次方程组的求解。

而高斯消元核心在于:

  • 两方程互换,解不变;
  • 一方程乘以非零数 𝑘k,解不变;
  • 一方程乘以数 𝑘k 加上另一方程,解不变。

高斯消元的过程可以分为以下几步:

  1. 增广矩阵行初等行变换为行最简形;
  2. 还原线性方程组;
  3. 求解第一个变量;
  4. 补充自由未知量;
  5. 列表示方程组通解。
#include <bits/stdc++.h>
using namespace std;
int n;
double a[100][100];
double eps=1e-4;
bool gauss(){
	for(int i=1;i<=n;i++){
		for(int k=i;k<=n;k++)if(fabs(a[k][i])>eps){swap(a[k],a[i]);break;}
		if(fabs(a[i][i])<eps)return 0;
		for(int j=n+1;j>=i;j--)a[i][j]/=a[i][i];
		for(int k=i+1;k<=n;k++){
			for(int j=n+1;j>=i;j--){
				a[k][j]-=a[k][i]*a[i][j];
			}
		}
	}
	for(int i=n-1;i>=1;i--){
		for(int j=i+1;j<=n;j++)
		a[i][n+1]-=a[i][j]*a[j][n+1];
	}
	return 1;
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n+1;j++){
			cin>>a[i][j];
		}
	}
	if(gauss()){
		for(int i=1;i<=n;i++)printf("%.2lf\n",a[i][n+1]);
	}
	else cout<<"No Solution";
	return 0;
}

矩阵求逆

矩阵求逆,即求矩阵的逆矩阵。矩阵是线性代数的主要内容,很多实际问题用矩阵的思想去解既简单又快捷。逆矩阵又是矩阵理论的很重要的内容,逆矩阵的求法自然也就成为线性代数研究的主要内容之一。
设A是数域上的一个n阶方阵,若在相同数域上存在另一个n阶矩B,使得: AB=BA=E。 则我们称B是A的逆矩阵,而A则被称为可逆矩阵。其中,E为单位矩阵。
典型的矩阵求逆方法有:利用定义求逆矩阵、初等变换法、伴随阵法、恒等变形法等。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int M=1e9+7;
int n;
int a[405][810];
int ksm(int a,int b){
    int ans=1;
    while(b){
        if(b&1)ans=ans*a%M;
        a=a*a%M;
        b>>=1;
    }
    return ans;
}
bool gauss(){
	for(int i=1;i<=n;i++){
		for(int k=i;k<=n;k++)if(a[k][i]){swap(a[k],a[i]);break;}
		if(!a[i][i])return 0;
        
        int kk=ksm(a[i][i],M-2);
		for(int j=1;j<=n;j++){
            if(j==i)continue;
            int p=a[j][i]*kk%M;
            for(int k=i;k<=n<<1;k++){
            	a[j][k]=((a[j][k]-p*a[i][k])%M+M)%M;
        	}
        }
        for(int j=1;j<=n<<1;j++) a[i][j]=a[i][j]*kk%M;
	}
    for(int i=1;i<=n;i++){
		for(int j=n+1;j<n<<1;j++) printf("%lld ",a[i][j]);
		printf("%lld\n",a[i][n<<1]);
	}
	return 1;
}
signed main(){
    ios::sync_with_stdio(0);
	cin.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cin>>a[i][j];a[i][i+n]=1;
		}
	}
	if(!gauss()) cout<<"No Solution";
	return 0;
}

组合计数基础

在组合计算方案数时有两种基本原理:

  • 加法原理 $\ \ $ 完成一件事的方法有 n 类,其中第 i 类方法包括 \(a_{i}\) 种不同的方法,且这些方法互不重合,则完成这件事共有 $a_{1}+a_{2}+\cdots+a_{n} $ 种不同的方法。

  • 乘法原理\(~~~~\)若完成一件事需要 n 个步骤,其中第 i 个步骤有 $ a_{i} $ 种不同的完成方法,且这些步骤互不干扰,则完成这件事共有 $a_{1} * a_{2} * \cdots * a_{n} $ 种不同的方法。

在组合计数中有组合与排列两种方式:

  • 排列:$ A_n^m \(是组合的数学表示,意思是从n个中选m个出来进行排列。\) ~A_n^m= \frac {n!}{(n-m)!}=n *(n-1) * \cdots * (n-m+1) \(。之所以\) A_n^m $它能够表达排列的意思,是因为在选出来的m个位置中,第一个有n种选法,第二个有n-1种选法......以此类推,第m个就有n-m+1种选法,再用乘法原理将它们相乘就是排列。
  • 组合:$ C_n^m \(是排列的数学表示,意思是从n个中选m个但不进行排列(不考虑顺序)。\)~ C_{n}^{m}=\frac{n!}{m!(n-m)!}=\frac{n *(n-1) * \cdots *(n-m+1)}{m *(m-1) * \cdots * 2 * 1} \(。之所以\) C_n^m $它能够表达组合的意思,是因为在排列中,有多种所选数字相同,但顺序不同的区别,所以会有重复项,将重负部分除掉即可(就是m!)。

性质

  • $ C_{n}{m}=C_{n} $
  • $ C_{n}^ {m}=C_{n-1}{m}+C_{n-1} $
  • $ C_{n}{0}+C_{n}+C_{n}{2}+\cdots+C_{n}=2^{n} $

证明:

  • 由组合数的定义,对于从 n 个不同元素中取出 m 个组成的每个集合,剩余未取出的元素也构成一个集合,两个集合一一对应,所以性质 1 成立。

  • 从 n 个不同元素中取出 m 个组成一个集合有两类方法:取 n 号元素,不取 n 号元素。若取 n 号元素,则应在剩余 n-1 个元素中选出 m-1 个,有 $ C_{n-1}^{m-1} $ 种取法。若不取 n 号元素,则应在剩余 n-1 个元素中选出 m 个,有 $ C_{n-1}^{m} $ 种取法。根据加法原理,性质 2 成立。

  • 从 n 个不同元素中取出若干个元素组成一个集合,有 n+1 类方法,分别是取出 $ 0,1,2, \cdots, n $ 个。根据加法原理,共有 $ C_{n}{0}+C_{n}+C_{n}{2}+\cdots+C_{n} $ 种方法。从另一个方面去想, n 个元素每个元素可以取或不取,总方法数为 $ 2^{n} $ ,二者相等,故性质 3 成立。

组合数的求法

  • 根据性质 2,用递推法可求出 $ 0 \leq y \leq x \leq n $ 的所有组合数 $ C_{x}^{y} $ ,复杂度 $ O\left(n^{2}\right) $ 。组合数的结果一般较大,若题目要求出 $ C_{n}^{m} $ 对一个数 p 取模后的值,并且 $ 1 \sim n $ 都存在模 p 乘法逆元,则可以先计算分子 $ n!\bmod p $ ,再计算分母 $ m!(n-m)!\bmod p $ 的逆元,乘起来得到 $ C_{n}^{m} \bmod p $ ,复杂度为 $ \mathrm{O}(n) $ 。
  • 若在计算阶乘的过程中,把 $ 0 \leq k \leq n $ 的每个 $ k!\bmod p $ 及其逆元分别保存在两个数组 j c 和 $ j c_{-} i n v $ 中,则可以在 $ \mathrm{O}(n \log n) $ 的预处理后,以 $ \mathrm{O}(1) $ 的时间回答 $ 0 \leq y \leq x \leq n $ 的所有组合数 $ C_{x}^{y} \bmod p=j c[x] * j c_{-} i n v[y] * j c_{-} i n v[x-y] \bmod p $ 。
  • 若题目要求我们对 $ C_{n}^{m} $ 进行高精度运算,为避免除法,可用 $ 0 \times 31 $ 节中"阶乘分解"的做法,把分子,分母快速分解质因数,在数组中保存各项质因子的指数。然后把分子,分母各个质因子的指数对应相减(把分母消去),最后把剩余质因子乘起来,时间复杂度为 $ O(n \log n) $。

code:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
int p;
int a,b;
int f[N],g[N];
int ksm(int a,int b){
    int c=1;
    while(b){
        if(b&1)c=c*a%p;
        a=a*a%p;
        b>>=1;
    }
    return c;
}
int ask(int n,int m,int p){
    int mb=1,ma=1;
    for(int i=1;i<=m;i++)mb=mb*i%p;
    for(int i=n-m+1;i<=n;i++)ma=ma*i%p;
    return ma*ksm(mb,p-2)%p;
}
signed main(){
	int T;cin>>T;
    while(T--){
        cin>>a>>b>>p;
        cout<<ask(a,b,p)<<'\n';
    }
	return 0;
}

二项式定理

\((a+b)^{n}=\sum_{k=0}^{n} C_{n}^{k} a^{k} b^{n-k}\)

证明:

数学归纳法。当 n=1 时, $ (a+b){1}=C_{n} a^{0} b{1}+C_{n} a^{1} b^{0}=a+b $ 成立。
假设当 n=m 时命题成立,当 n=m+1 时:

\(\begin{array}{l} (a+b)^{m+1}=(a+b)(a+b)^{m}=(a+b) \sum_{k=0}^{m} C_{m}^{k} a^{k} b^{m-k} \\\\ =\sum_{k=0}^{m} C_{m}^{k} a^{k+1} b^{m-k}+\sum_{k=0}^{m} C_{m}^{k} a^{k} b^{m-k+1}=\sum_{k=1}^{m+1} C_{m}^{k-1} a^{k} b^{m-k+1}+\sum_{k=0}^{m} C_{m}^{k} a^{k} b^{m-k+1} \\\\ =\sum_{k=0}^{m+1}\left(C_{m}^{k-1}+C_{m}^{k}\right) a^{k} b^{m-k+1}=\sum_{k=0}^{m+1} C_{m+1}^{k} a^{k} b^{m+1-k} \end{array}\)

Lucas 定理

对于素数 p ,有

$\binom{n}{k} \equiv\binom{\lfloor n / p\rfloor}{\lfloor k / p\rfloor}\binom{ n \bmod p}{k \bmod p} \quad(\bmod p) $.

其中,当 n<k 时,二项式系数 \(\binom{n}{k}\) 规定为 0 。

Lucas 定理指出,模数为素数 𝑝p 时,大组合数的计算可以转化为规模更小的组合数的计算。在右式中,第一个组合数可以继续递归,直到 𝑛,𝑘 <𝑝n,k<p 为止;第二个组合数则可以直接计算,或者提前预处理出来。写成代码的形式就是:

long long Lucas(long long n, long long k, long long p) {
  if (k == 0) return 1;
  return (C(n % p, k % p, p) * Lucas(n / p, k / p, p)) % p;
}

卡特兰数

Catalan 数经常出现在各类计数问题中。比利时数学家 在 1958 年研究括号序列计数问题时发现了这一数列,它也因此得名。

Catalan 数满足如下递推关系:

\(C_{n}=\left\{\begin{array}{ll} 1, & n=0 \\ \sum_{i=0}^{n-1} C_{i} C_{n-1-i}, & n>0 \end{array}\right.\)

数列的前几项为:

\(1,1,2,5,14,42,132,429,1430, \ldots\)

常见形式

Catalan 数有如下常见的表达式:

\(\begin{array}{c} C_{n}=\frac{1}{n+1}\binom{2 n}{n}=\frac{(2 n)!}{n!(n+1)!}, n \geq 0 \\ C_{n}=\binom{2 n}{n}-\binom{2 n}{n+1}, n \geq 0 \\ C_{n}=\frac{(4 n-2)}{n+1} C_{n-1}, n>0, C_{0}=1\\ \end{array}\)

Catalan 数的这些形式都可以高效计算:前两个形式将它转换为阶乘和组合数的计算问题,第三个形式则提供了顺次计算的递推公式。

容斥与莫比乌斯函数及概率期望

容斥原理

在计数时,必须注意没有重复,没有遗漏。为了使重叠部分不被重复计算,人们研究出一种新的计数方法,这种方法的基本思想是:先不考虑重叠的情况,把包含于某内容中的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去,使得计算的结果既无遗漏又无重复,这种计数的方法称为容斥原理。
如果被计数的事物有A、B、C三类,那么,A类和B类和C类元素个数总和= A类元素个数+ B类元素个数+C类元素个数—既是A类又是B类的元素个数—既是A类又是C类的元素个数—既是B类又是C类的元素个数+既是A类又是B类而且是C类的元素个数。(A∪B∪C = A+B+C - A∩B - B∩C - C∩A + A∩B∩C)

$
\begin{array}{l}
\left|A_{1} \cup A_{2} \cup \cdots \cup A_{m}\right|= \
\sum_{1 \leq i \leq m}\left|A_{i}\right|-\sum_{1 \leq i<j \leq m}\left|A_{i} \cap A_{j}\right|+\sum_{1 \leq i<j<k \leq m}\left|A_{i} \cap A_{j} \cap A_{k}\right|-\cdots+(-1)^{m-1}\left|A_{1} \cap A_{2} \cap \cdots \cap A_{m}\right|
\end{array}
$

也可表示为
设 S 为有限集,$ A_{i} \subseteq S(i=1,2, \cdots, n, n \geq 2) $ ,则

$ \left|\bigcup_{i=1}^{n} A_{i}\right|=\sum_{k=1}{n}(-1) \sum_{1<i_{1}<i_{2}<\cdots<i_{k}<n}\left|A_{i_{1}} \cap A_{i_{2}} \cap \cdots \cap A_{i_{k}}\right| $

由于

$
\begin{array}{l}
\overline{A_{1} \bigcup A_{2} \bigcup \ldots \bigcup A_{n}}=\overline{A_{1}} \bigcap \overline{A_{2}} \bigcap \cdots \bigcap \overline{A_{n}} \
\overline{A_{1} \bigcap A_{2} \bigcap \cdots \bigcap A_{n}}=\overline{A_{1}} \bigcup \overline{A_{2}} \bigcup \ldots \bigcup \overline{A_{n}}
\end{array}
$

所以

$ \left|\overline{A_{1}} \bigcap \overline{A_{2}} \bigcap \cdots \bigcap \overline{A_{n}}\right|=N-\left|A_{1} \bigcup A_{2} \bigcup \ldots \bigcup A_{n}\right| $

两个集合的容斥关系公式:$ A \cup B=|A \cup B|=|A|+|B|-|A \cap B| $

$ \text { 三个集合的容斥关系公式: }|\mathrm{A} \cup \mathrm{~B} \cup \mathrm{C}|=|\mathrm{A}|+|\mathrm{B}|+|\mathrm{C}|-|\mathrm{A} \cap \mathrm{~B}|-|\mathrm{B} \cap \mathrm{C}|-|\mathrm{C} \cap \mathrm{~A}|+ |\mathrm{A} \cap \mathrm{B} \cap \mathrm{C}| $

莫比乌斯函数

莫比乌斯函数是指以下的函数:
$ \mu(n)=\left{\begin{array}{ll}
1 & \text { 若 } n=1 ; ~ \
(-1)^{k} & \text { 若 } n \text { 无平方数因数, 且 } n=p_{1} p_{2} \ldots \ldots p_{k} ; \
0 & \text { 若 } n \text { 有大于 } 1 \text { 的平方数因数。 }
\end{array}\right.$

莫比乌斯函数完整定义的通俗表达:
1)莫比乌斯函数μ(n)的定义域是N;
2)μ(1)=1;
3)当n存在平方因子时,μ(n)=0;
4)当n是素数或奇数个不同素数之积时,μ(n)=-1;
5)当n是偶数个不同素数之积时,μ(n)=1。

性质1
莫比乌斯函数是一个数论函数,它是一个积性函数。
\( \sum_{d \mid n} \mu(d)=\left\{\begin{array}{ll} 1 & (n=1) \\ 0 & (n>1) \end{array}\right. \)

通俗地讲,当 \(N\) 包含相等的质因子时, \(\mu(N)=0\)

\(N\) 的所有质因子各不相等时:

\(N\) 有偶数个质因子, \(\mu(N)=1\)

\(N\) 有奇数个质因子, \(\mu(N)=-1\)

证明:
(1)当 n=1 时显然
(2)当 $ \mathrm{n} \neq 0 时,将 n 分解可以得到 n=p_{1}^{a_{1}} p_{2}^{a_{2}} \ldots p_{k}^{a_{k}} $ 在 n 的所有因子中,$ \mu $ 值不为零的只有所有质因子次数都为 1 的因子,其中质因数个数为 r 个的因子有 $C_{k}^{r} $ 个那么显然有:

$ \sum_{d \mid n} \mu(d)=C_{k}{0}-C_{K}+C_{k}{2}+\ldots+(-1) C_{k}{k}=\sum_{i=0}(-1)^{i} C_{k}^{i} $

性质2
对任意正整数 n 有:

$ \sum_{d \mid n} \frac{\mu(d)}{d}=\frac{\varphi(n)}{n} $

int pri[N],vis[N],sum[N],mo[N];
void init(){
    mo[1]=1;
    for(int i=2;i<N;i++){
        if(!vis[i]){
            pri[++cnt]=i;
            mo[i]=-1;
        }
        for(int j=1;i*pri[j]<N;j++){
            vis[i*pri[j]]=1;
            if(i%pri[j]==0)break;
            mo[i*pri[j]]=mo[i]*-1;
        }
    }
    for(int i=1;i<N;i++)sum[i]=mo[i]+sum[i-1];
}

概率期望

在概率论和统计学中,期望值是指在一个随机变量试验中每次可能结果的概率乘以其结果的总和。换句话说,期望值是随机试验在同样的机会下重复多次的结果计算出的等同“期望”的平均值。需要注意的是,期望值并不一定等同于常识中的“期望”——“期望值”也许与每一个结果都不相等。

定义

若随机变量 X 的取值有 \(x_{1}, x_{2}, \cdots\) ,一个随机事件可表示为 \(X=X_{i}\) ,其概率为 \(P\left(X=X_{i}\right)=p_{i}\) ,则称 $E(X)=\sum p_{i} x_{i} $ 为随机变量 X 的数学期望。通俗地讲,数学期望是随机变量取值与概率的乘积之和。

例如在掷两枚骰子的点数实验中,样本空间是由 36 个样本点构成的集合,每个样本点可写作 (a, b) ,其中 $$ 1 \leq a ; b \leq 6 $$ 。随机变量有多种,不妨以"掷出的点数之和 X "为例,则随机变量 X 的取值为 \(2 \sim 12\) 。随机事件可描述为"掷出 X 点",即由 a+b=X 的样本点 (a, b) 构成的子集。掷出 8 点的概率 P(X=8)=5 / 36 。掷出的点数的数学期望为:

$ \frac{1}{36} *(2+12)+\frac{1}{18} *(3+11)+\frac{1}{12} *(4+10)+\frac{1}{9} *(5+9)+\frac{5}{36} *(6+8)+\frac{1}{6} * 7=7 $

性质

因为期望是线性的,所以有:
\(E(aX=bY)=a*E(X)+B*E(Y)\)

博弈论

博弈论(game theory)是经济学的一个分支,主要研究具有竞争或对抗性质的个体,在特定规则下所产生的各种行为。博弈论关注博弈中个体的预期行为与实际行为,并研究其最优策略。

通俗地讲,博弈论主要研究的是:在一个游戏中,进行游戏的多位玩家如何选择策略。

合作/非合作博弈

合作博弈(cooperative game)是指参与者可以结成联盟、相互合作的博弈。在这类博弈中,个体的不合作行为往往会受到某种外部机制的惩罚。与之相对,非合作博弈中并不存在这样的机制,因此,参与者要么无法结成联盟,要么只能依赖可信的威胁机制维持合作。

相比合作博弈,非合作博弈的研究更为系统和成熟。

对称/非对称博弈

对称博弈中,不同参与者在做出相同行为时获得的收益是相同的,也就是说,收益只取决于行为本身,而与行为者的身份无关。不满足这一条件的博弈称为 非对称博弈

零和/非零和博弈

零和博弈指的是无论各方采取何种行为,所有参与者的收益总和始终为零。通常讨论的零和博弈涉及两名参与者,此时,一方的收益必然是另一方的损失。相对地,非零和博弈允许多方共赢或共输,包括 正和博弈负和博弈等。

公平组合博弈

公平组合游戏中,最基础也最重要的是正常 Nim 游戏。Sprague–Grundy 定理指出,所有正常规则的公平组合游戏都等价于一个单堆 Nim 游戏。由此,可以发展出 Sprague–Grundy 函数和 Nim 数的概念,它们完全地刻画了一个正常规则的公平组合游戏。

Nim 游戏

共有 n 堆石子,第 i堆有 \(a_i\) 枚石子。两名玩家轮流取走任意一堆中的任意多枚石子,但不能不取。取走最后一枚石子的玩家获胜。

Nim 游戏中,局面可能的变化可以用博弈图来描述。

将每一个可能的状态都看作是图中的一个结点,并将状态向它的后继状态(即通过一次操作可以达到的状态)连边,就得到一个有向无环图,这就是博弈图。图是无环的,因为 Nim 游戏中,每次操作,石子的总数量都是严格减少的。

由于 Nim 游戏是公平组合游戏,每个玩家是否有必胜策略,只取决当前游戏所处的状态,而与玩家的身份无关。因此,所有状态可以分为(先手)必胜状态 和(先手)必败状态

所有公平组合游戏中,博弈图都是有向无环图。所以,通过这三条性质,可以在绘制出博弈图后,在 𝑂(|𝑉| +|𝐸|)的时间内,计算出每个状态是必胜状态还是必败状态。其中,|𝑉|为博弈图的状态数目,|𝐸|为边数,即所有状态可以采取的行动的数量的总和。

通过绘制博弈图,可以在 Ω(∏𝑛𝑖=1𝑎𝑖)的时间内求出某一局面是否是先手必胜。但是,这样做的复杂度过高,无法实际应用。实际上,可以发现 Nim 游戏的状态是否先手必胜,只与当前局面的石子数目的 Nim 和有关。

Nim 游戏中,状态 \((𝑎_1,𝑎_2,⋯,𝑎_𝑛)\) 是必败状态 P,当且仅当 Nim 和\(𝑎_1⊕𝑎_2⊕⋯⊕𝑎_𝑛=0.\)

由此,可以在 𝑂(𝑛) 时间内判断 Nim 游戏的一个状态是否为先手必胜状态。

证明

对所有可能的状态应用归纳法:

  1. 如果 \(𝑎_i\) =0对所有 𝑖 =1,⋯,𝑛都成立,该状态没有后继状态,且 Nim 和等于 0,命题成立。

  2. 如果 𝑘 =\(𝑎_1 ⊕𝑎_2 ⊕⋯ ⊕𝑎_𝑛 ≠0\),那么,需要证明该状态是必胜状态。也就是说,需要构造一个合法移动,使得后继状态为必败状态;由归纳假设,只需要证明后继状态满足$ 𝑎′_1 ⊕𝑎′_2 ⊕⋯ ⊕𝑎′_𝑛 =0$。利用 Nim 和(即异或)的性质,这等价于说,存在一堆石子,将 𝑎𝑖拿走若干颗石子,可以得到 \(𝑎_𝑖 ⊕𝑘\),亦即 \(𝑎_𝑖 >𝑎_𝑖 ⊕𝑘\)

    实际上,设 𝑘 的二进制表示中,最高位的 1 是第 𝑑 位。那么,一定存在某个$$ 𝑎_𝑖$$,使得它的二进制第 𝑑 位是 1。对于相应的石子堆,就一定有 \(𝑎_𝑖>𝑎_𝑖 ⊕𝑘\),因为 \(𝑎_𝑖 ⊕𝑘\)中第 𝑑 位为 0,更高位和 \(𝑎_𝑖!\) 一样。

  3. 如果 \(𝑎_1 ⊕𝑎_2 ⊕⋯ ⊕𝑎_𝑛 =0\),那么,需要证明该状态是必败状态。由归纳假设可知,只要证明它的所有后继状态的 Nim 和都不是 0。这是必然的,任何合法移动将 \(𝑎_𝑖\)变为 \(𝑎′_𝑖 ≠𝑎_i\),就必然会使得 Nim 和变为 \(𝑎′_𝑖 ⊕𝑎_𝑖 ≠0!\)

posted @ 2025-10-20 10:17  Austin0928  阅读(7)  评论(0)    收藏  举报