数论

\(update: 2025/8/5\)

其实它不简单,但也不难

初等数学

方差

常规计算:

\[s^2=\sum_{i=1}^n \ \ (a_i-\overline{a})^2 \]

推导:

\[s^2=\frac{\sum_{i=1}^n \ a_i^2}{n}-\overline{x}^2 \]

组合数学

直观且简单地说就是排列与取数问题

加法原理&乘法原理

加法原理: 做一件事有多类方式,等级相同(各部分相互间独立),则做这件事的方法数量为各类方式之和
乘法原理:做一件事有多步,各部分之间有先后顺序,则做这件事的方法数量为各类方式之积

排列

其一

\(n\)个不同的人,编号为\(1,2,3...n\),列队站成一行
每种列队的方法,都是长为\(n\)的一个排列

共有\(n!\)种方法

即选第一人时有\(n\)
选第二人时有\(n-1\)
......
根据乘法原理求得有\(n!\)


其二

如果是从\(n\)个人里选出\(m\)个人,让他们站成一行;
这个问题的答案记作\(A^m_n\)
乘法原理得

\[n^{\underline{m}}=A^m_n=n*(n-1)*...*(n-m+1)=\frac{n!}{(n-m)!} \]

组合

除法原理

\(n\)个人中选出\(m\)个人,问多少种方法
这个问题的答案记作\(C^m_n\),但现在更常用\((^n_m)\)
乘法原理得\(A^m_n=(^n_m)*m!\)
因此

\[(^n_m)=\frac{n^{\underline{m}}}{m!}=\frac{n!}{(n-m)!m!} \]

我们也可以将上面的论证称为"除法原理"
如果做一件事分为两步,共\(n\)种方法,完成第二步有\(n_2\)种方法
那么完成第一步有\(n/n_2\)种方法

圆排列

如果将上述问题转化为把\(n\)个人排成一环,并把旋转后相同的排法看成一种,求有多少种排法;

乘法原理:选出一号右边的人,再选出一号右边的右边的人...

除法原理:考虑\(n\)个人排成一行,选出\(n\)个人排成一个环,再选出一个人做第一行的第一个人

上述两种方法会得到相同的结果:\(n!/n=(n-1)!\)


burnside引理(待补)


带队

现有三个老师,\(n\)个同学,每个老师带一些同学组成一队,假设每个老师分别带领\(n_A,n_B,n_C\)个人,求方案数
上面的问题答案记作

\[(^n_{n_A,n_B,n_C})=\frac{n!}{n_A!n_B!n_C!} \]

数学上,可以看成把\(n\)个元素放进三个不同的集合,每个集合大小给定,共有多少种分法


隔板法

考虑这样一个问题
求方程

\[x_1+x_2+...+x_m=n \]

的正整数解的个数
如果我们换个角度想,考虑这有\(n\)个小球,我们要将这些小球分成\(m\)

于是我们将原问题转化为一个组合问题,易知它的方案和原题一一对应

那么我们再考虑将\(n\)个小球排成一行,那么有\(n-1\)个空隙,我们要选\(m-1\)个,插上一个隔板(这也许就是此方法名字的由来),则共有\((^{n-1}_{m-1})\)种方案

这种转化是很多看似与组合数学无关的问题的第一步解法 : 尝试将其转化为已知问题求解;(下面的二项式定理也是如此)
例题(待补)

二项式定理

考虑这样一个拆括号问题

\[(x+y)^2=x^2+2xy+y^2 \]

这个好拆

\[(x+y)^n \]

怎么拆

由此引出二项式定理

考虑\((x+y)^n\)拆开写成\((x+y)*(x+y)*(x+y)*(x+y)\)...的形式

于是问题转化为对于每一个\((x+y)\),我们取左边还是取右边的组合问题
最终得到以下式子

\[(x+y)^n=\sum^n_{i=0}(_i^n)x^iy^{n-i} \]


状压DP(待补)


杨辉三角

真的很好用(前提你知道怎么用)

观察下面的三角形
\(1\)
\(1\) \(1\)
\(1\) \(2\) \(1\)
\(1\) \(3\) \(3\) \(1\)
\(1\) \(4\) \(6\) \(4\) \(1\)
\(1\) \(5\) \(10\) \(10\) \(5\) \(1\)

我们发现,每一个数都是上两个数的和(最左侧和最右侧的两列除外),因此我们得出杨辉三角的递推式

    for(int i=1;i<=n;i++){
        a[i][0]=a[i][i]=1;
        for(int j=1;j<i;j++){
            a[i][j]=a[i-1][j-1]+a[i-1][j];
        }
    }
多数情况下它只能作为一个优化用的方法,见luogu P2822

组合数性质

  • \[(^n_m)=(^{n-1}_{m-1})+(^{n-1}_m) \]

  • \[(^n_m)=\frac{n-m+1}{m}(^{n}_{m-1})=(^{n}_{n-m}) \]

可以用来计算杨辉三角的一行

  • \[\sum^n_{i=1}(^i_m)=(^{n+1}_{m+1}) \]

这里我们默认如果\(n<m\),那么\((^n_m)=0\)
这个性质是杨辉三角的按列求和,也称作"上指标求和"

  • \[\sum^n_{i=0}(^n_i)=2^n \]

  • \[\sum^k_{i=0}(^n_i)(^m_{k-i})=(^{n+m}_k) \]

组合意义证明

要证明代数的等式,我们可以构造一个组合问题
这个组合问题有两个视角.一个给出等式左边,一个给出等式右边
由于两边都计算了同一个问题的答案,左右相等

事实上,上面的所有性质都能通过此方法证明

组合数学杂项

等价类

等价关系
我们定义的,用以分辨等价的关系,

例如:项链的染色等价,是定义成旋转后相同的两个染色等价,也可以定义成,作任意次旋转或镜面对称后,两染色方案相同,则两方案等价

好的等价关系
一般满足以下三个条件

  • 自反 : \(a\) ~ \(a\)
  • 对称 : \(a\) ~ \(b\),则 \(b\) ~ \(a\)
  • 传递 : \(a\) ~ \(b\) ,\(b\) ~ \(c\) ,则 \(a\) ~ \(c\)

事实上,只要一个等价关系满足上述三个条件,就是一个好等价关系,我们可以因此把集合分为多个等价类
\(a\)所在的等价类<\(a\)>={\(b|b\)~\(a\)}
通常我们会找一个代表元来区分不同等价类

例如:并查集

鸽笼原理(抽屉原理)

把&n&只鸽子放在\(m\)个笼子里,则至少有一个笼子放\(\lceil n/m \rceil\)只鸽子

原理极易理解,但如同杨辉三角一样,你需要知道何时使用它

初等数论

整除

如果\(a\)%\(b==0\),则称\(b\)整除\(a\),记作 \(b|a\)

一些显然的性质

  • \(d|a,d|b\Rightarrow d|(a\pm b)\)
  • \(b|a\Rightarrow bd|ad\)
  • \(b|a,d|a,d|b\Rightarrow \frac{b}{d}|\frac{a}{d}\)

\(gcd\) & \(lcm\)

\(gcd\):最大公约数
\(lcm\):最小公倍数
显然
\(gcd(a,b)*lcm(a,b)=ab\)

gcd(欧几里得算法)

事实上,c++自带__gcd函数可以求gcd

\(gcd(a,b)=gcd(b,a \bmod b)\)

\(code\)

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

exgcd(扩展欧几里得算法)

考虑这样一个问题
如何求\(ax+by=c\)的一组正整数解
\(exgcd\)给出了求\(ax+by=gcd(a,b)\)的方法

\(code\)

void exgcd(int a,int b,int &x,int &y){
	if(!b) x=1,y=0;
	else exgcd(b,a%b,y,x),y-=a/b*x;
}

使用时

    int x,y
    exgcd(a,b,x,y)
    x=x*c/__gcd(a,b);

再来考虑如何让求的\(x\)最小

    x=(x%b+b)%b;//因为要让x保证非负时尽可能小
例题

luogu P5656 【模板】二元一次不定方程 (exgcd)

\(code\)

//May all the beauty be blessed.
#include<bits/stdc++.h>
#define int long long
using namespace std;
int t;
int a,b,c;
void exgcd(int a,int b,int &x,int &y){
	if(!b) x=1,y=0;
	else exgcd(b,a%b,y,x),y-=a/b*x;
}
int gcd(int x,int y){
	if(!y) return x;
	else return gcd(y,x%y);
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>t;
	while(t--){
		int x,y;
		cin>>a>>b>>c;
		int d=gcd(a,b);
		if(c%d){
			cout<<-1<<'\n';
			continue;
		}
		exgcd(a,b,x,y);
		x=x*c/d,y=y*c/d;
		int xl=b/d,yl=a/d;
		int k=ceil((1.0-x)/xl);
		x+=xl*k;
		y-=yl*k;
		if(y<=0){
			int yy=y+yl*ceil((1.0-y)/yl);
			cout<<x<<" "<<yy<<'\n';
		}else cout<<(y-1)/yl+1<<" "<<x<<" "<<(y-1)%yl+1<<" "<<x+(y-1)/yl*xl<<" "<<y<<'\n';
	}
}

逆元

在模的意义下,除法无法正常使用;
因此我们需要将除法改成乘法,以确保能正常取模

逆元存在条件

设求\(x\)的逆元,模\(p\)
当且仅当\(gcd(x,p)=1\)时存在逆元

证明(反证法):

\(gcd(x,p)=d\),若\(d!=1\)
则对于\(x\equiv1 \pmod p\),有\(x-1\equiv0 \pmod p\)
\(x=kd\),则不存在\(d|x-1\)
则不存在\(x-1 \equiv 0 \pmod p\)
证反毕

\(exgcd\)求法

条件:当\(gcd(x,p)=1\),即存在逆元时

void exgcd(int a,int b,int &x,int &y){
	if(!b) x=1,y=0;
	else exgcd(b,a%b,y,x),y-=a/b*x;
}

//用法
    int x,y;
	exgcd(a,mod,x,y);
	x=(x%mod+mod)%mod;//防止出负

\(crt\) (中国剩余定理)

\(b_1,b_2,....b_n\)两两互质,
求解同余方程组
\(\begin{cases} x\equiv a_1 (\bmod b_1)\\ x\equiv a_2 (\bmod b_2)\\ ...\\ x\equiv a_n (\bmod b_n) \end{cases}\)

想法:
先构造一个\(y_1\),使
\(\begin{cases} y_1\equiv 1 (\bmod b_1)\\ y_1\equiv 0 (\bmod b_2)\\ ...\\ y_1\equiv 0 (\bmod b_n) \end{cases}\)
同理,求\(y_2,y_3,...,y_n\)
易知可通过\(exgcd\)求出\(x_i=y_i*a_i\),又由于$$\prod_{j=1,j!=i}^n b_j|y_i$$
得出$$y_i=\prod_{j=1,j!=i}^n b_j*k_i$$(其中\(k_i\)为一个系数),最终得如下式子

\[x=\sum_{i=1}^n \prod_{j=1,j!=i}^n b_j*k_i*a_i(\bmod \prod_{j=1}^n b_i) \]

excrt(扩展中国剩余定理)

若上述\(b_1,...b_n\)不互质怎么办?
考虑合并方程
考虑\(n=2\)
\(\begin{cases} x=k_1*b_1+a_1\\ x=k_2*b_2+a_2\\ \end{cases}\)
联立得\(k_1*b_1-k_2*b_2=a_2-a_1\)这个方程有解当且仅当\(gcd(k_1,k_2)|(a_2-a_ 1)\)

则我们得到一组特解\((k_1,k_2)\)使得上述两个方程成立,带入得出\(x=x_{1,2}\)的特解
\(x\equiv x_{1,2} \bmod lcm(b_1,b_2)\)

重复此过程得解
实现(luogu P4777):

//May all the beauty be blessed.
#include<bits/stdc++.h>
#define int __int128
using namespace std;
long long n;
int ax,bx,a[100010],b[100010];
void exgcd(int al,int bl,int &x,int &y){
	if(!bl) x=1,y=0;
	else exgcd(bl,al%bl,y,x),y-=al/bl*x;
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++){
		long long x,y;
		cin>>x>>y;
		a[i]=x,b[i]=y;
	}
	ax=a[1],bx=b[1];
	for(int i=2;i<=n;i++){
		int x,y;
		exgcd(ax,a[i],x,y);
		int d=__gcd(ax,a[i]);//在这里可以特判有无解(d|(b[i]-bx))
		x=x*(b[i]-bx)/d;//得到一组特解
		x=(x%a[i]+a[i])%a[i];//用另一个模数对其取余,保证解的正确性
//		cout<<x<<" ";
		bx+=x*ax;
		ax=ax*a[i]/d;//lcm(a[i],ax)
		bx=(bx%ax+ax)%ax;
	}
	long long y=bx;
	cout<<y;
}

拉格朗日插值法

据说其与\(crt\)有很深的联系,但我没看出来

已知\(f\)是一个多项式,并给出\(n\)个对应的点值:\(f(x_1)=y_1,f(x_2)=y_2...,f(x_n)=y_n\)

求次此多项式(或是\(f(x_k)=?\))
想法:暴力构造一系列多项式,使得\(f_i(x_i)=1\)\(f_j(x_j)=0 (i!=j)\)
再加到一起构成\(f(x)=y_1f_1(x_1)+y_2f_2(x_2)+...+y_nf_n(x_n)\)

于是我们来考虑如何构造一个多项式\(f_i\)满足条件,
一个比较直接的想法是$$f_i(x)=\prod_{j!=i} (x-x_j)$$
而为了让\(f_i(x_i)=1\),我们令原多项式除以\(x=x_i\)时对应的值

最终求得$$f_i(x)=\prod_{j!=i} \frac{(x-x_j)}{(x_i-x_j)}$$

而自然$$f(x)=\sum_{i=1}^n\ y_if_i(x)$$

数论函数(待补)

数论函数:定义域为正整数的函数,可以视作数列
加性函数:
积性函数:\

欧拉函数(待补)

\(Dirichlet\)函数 (待补)

莫比乌斯函数(待补)

posted @ 2025-05-07 16:52  破碎中永恒  阅读(62)  评论(5)    收藏  举报