Loading [MathJax]/jax/element/mml/optable/MathOperators.js

数论,数学

gcd and lcm

Code

int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int lcm(int a,int b){return a/gcd(a,b)*b;}

gcd的几条性质

gcd(xa1,xb1)=xgcd(a,b)1

证明:
gcd(xa1,xb1)
=gcd(xb1,xaxb)
=gcd(xb1,xb(xab1))
=gcd(xb1,xab1)

gcd(fib[i],fib[j])=fib[gcd(i,j)]

fib[] 为广义斐波那契数列)

证明:
gcd(fib[i+j],fib[j])
=gcd(fib[j],fib[i+j]fib[j])
=gcd(fib[j],fib[i1]fib[j]+fib[i]fib[j+1]fib[j])
=gcd(fib[j],fib[i]fib[j+1])
=gcd(fib[j],fib[i])

线性筛

int pr[maxn],tot;
bool check[maxn];
void init(int n){
    check[1]=1;
    for(int i=2;i<=n;i++){
        if(!check[i]){
            pr[++tot]=i;
        }
        for(int j=1;j<=tot&&i*pr[j]<=n;j++){
            check[i*pr[j]]=1;
            if(i%pr[j]==0)break;
        }
    }
}

理论上来讲 n 以内的质数个数大约在 n/ln(n) 个左右

欧拉定理

aφ(n)1(%n)(gcd(a,n)=1)

S={x1,x2,...,xφ(n)} 为所有与 n 互质且 n 的数。
显然 xixj(ij)(%n) 不成立。
再设 T={ax1,ax2,...,axφ(n)}
\because \gcd(a,n)=1
\therefore a*x_i≡a*x_j(i≠j)(\% n) 不成立
\therefore S=T
\therefore \prod_{i=1}^{\varphi(n)}a*x_i≡\prod_{i=1}^{\varphi(n)}x_i(\% n)
\therefore a^{\varphi(n)}≡1(\% n)

扩展欧拉定理

a^b\equiv \begin{cases} a^{b\bmod\varphi(p)},\,&\gcd(a,\,p)=1\\ a^b,&\gcd(a,\,p)\ne1,\,b<\varphi(p)\\ a^{b\bmod\varphi(p)+\varphi(p)},&\gcd(a,\,p)\ne1,\,b\ge\varphi(p) \end{cases} \pmod p

费马小定理

a^{p-1}≡1(\% p)(p\text{ is prime})

Code

O(n)1-n 的欧拉函数

void init(int n){
	phi[1]=1;	
	for(int i=2;i<=n;i++){
		if(!check[i]){
			pr[++tot]=i;
			phi[i]=i-1;
		}
		for(int j=1;j<=tot&&i*pr[j]<=n;j++){
			check[i*pr[j]]=1;
			if(i%pr[j]==0){
				phi[i*pr[j]]=phi[i]*pr[j];
				break;
			}
			else phi[i*pr[j]]=phi[i]*phi[pr[j]];
		}
	}
}

O(\sqrt{n})n 的欧拉函数

int phi(int n){
    int x=n,ret=n;
    for(int i=2;i*i<=n&&x>1;i++){
        if(x%i==0){
            ret=ret/i*(i-1);
            while(x%i==0)x/=i;
        }
    }
    if(x>1)ret=ret/x*(x-1);
    return ret;
}

逆元

逆元的引入

在做组合数取模的时候,常常要求(a/b)\%p^{[1]},然而不同于加减乘,除法取模没有(a/b)\%p=(a\%p/b\%p)\%p的性质。因此,我们引入乘法逆元的概念。

a* b≡1(\%p),则设b=inv(a),称ba的逆元,满足(a*b)\%p=(a\%p*b\%p)\%p。这样,除法转换为乘法,就可以了。

所有的有理数都有一个与其对应的逆元。因此,对于两个整数A,B,要计算\frac{A}{B}(实数除法)时,A不一定要被B整除。

对于两个取模过的数,逆元是怎么输出商的?它实际上是在对给定的取模过的数a,b,找最小的两个A,B,满足A=x* p+a,B=y* p+b,A\%B=0,并返回A/B

求逆元的几种常用方法

1. 扩展欧几里得

欧几里得定理

想必都知道gcd(a,b)=gcd(b,a%b)

解关于x,y的方程ax+by=gcd(a,b)

首先,我们先解出方程的一个特解,再通过特解推出其余的通解即可。

如何求特解

我们来看下面两个方程:

ax_1+by_1=gcd(a,b)

bx_2+(a\%b)y_2=gcd(b,a\%b)

\because gcd(a,b)=gcd(b,a\%b),

\therefore ax_1+by_1=bx_2+(a\%b)y_2

\because a\%b=a-floor(a/b)* b^{[2]}

\therefore ax_1+by_1=ay_2+b(x_2-floor(a/b)* y_2)

由等式两边的系数关系得x_1=y_2y_1=x_2-floor(a/b)* y_2
于是形成了一种递归关系,可用递归解决。

递归终止状态

我们知道在计算最大公约数的过程中,b最终会等于0,此时a=gcd(A,B),因此,这时方程化为a* x=gcd(A,B),解得x=1,y=0

如何求通解

求得一组特解之后,我们发现,对于方程ax+by=gcd(a,b),当x增加b/gcdy减少a/gcd时,等式仍成立。

证明

ax项增加a* b/gcdby项减少a* b/gcd

于是可求得所有通解。

如何求最小非负整数解

此处以x为例,y同理。我们让x一直减B/gcd直至求出最小解,即让x\%(B/gcd)即可。

解关于x,y的方程Ax+By=C

我们发现,当C不能整除gcd(A,B)时,方程就不能化为ax+by=gcd(a,b)的形式,因此就无解。否则有无数解,将方程两边同时除以\frac{C}{gcd(A,B)}求解即可。

Code
typedef long long D;
D egcd(D a,D b,D &x,D &y){
	if(b==0){
		x=1;
		y=0;
		return a;
	}
	D ans=egcd(b,a%b,x,y),tmp=x;
	x=y;
	y=tmp-a/b*y;
	return ans;
}
D cal(D a,D b,D c){
	D x,y,g=egcd(a,b,x,y);
	if(c%g!=0)return -1;
	b=abs(b/g);
	x=(x*(c/g)%b+b)%b;
	return x;
}

利用扩展欧几里得求乘法逆元

因为a* x≡1(%p)
所以a* x+b* y=1
此时,若1\%gcd(a,b)≠1,即gcd(a,b)≠1,则该方程无解。
否则,设特解为x_0,最小非负整数解x=x_0\%m。当m<0时,由于计算机取模一个负数与数学上的意义不同,所以应把模数取绝对值。当x_0<0时,取模的结果是一个负数,所以把答案加上m即可。

复杂度为\log级。

Code

typedef long long D;
D egcd(D a,D b,D &x,D &y){
	if(b==0){
		x=1;
		y=0;
		return a;
	}
	D ans=egcd(b,a%b,x,y),tmp=x;
	x=y;
	y=tmp-a/b*y;
	return ans;
}
D cal(D a,D m){
	D x,y,g=egcd(a,m,x,y);
	if(g!=1)return -1;
	m=abs(m/g);
	x=(x%m+m)%m;
	return x;
}

2. 利用费马小定理

p为质数时a^{p-1}≡1(\%p) ,对a* x≡1(\%p)x=a^{p-2}\%p

复杂度为\log级。

Code

typedef long long D;
D qpow(D x,D y,D p){
	D ans=1;
	while(y){
		if(y&1)ans=ans*x%p;
		x=x*x%p;
		y>>=1;
	}
	return ans;
}
D cal(D a,D p){
	return qpow(a,p-2,p);
}

组合数取模(Lucas 定理)

由于题目中给的p一般都是质数,所以下面我们默认p为质数

1. 错误方法

由上面的结论,我们得出C(n,m)=\frac{n!}{m!(n-m)!}=n!* inv(m!)* inv((n-m)!)
直接使用扩展欧几里得或费马小定理求逆元来实现除法取模。

此方法的错误之处在于,对a* x≡1(\%p),a有逆元的前提条件时a,p互质。当a,p不互质,即ap的倍数时,不存在逆元,也就无法计算。

比如计算C(7,5)\%5,正确答案应该是\frac{7* 6}{1* 2}\%5=21\%5=1,但计算过程中出现了5的倍数,取模5之后就变为0,因此最后答案输出了0

2. Lucas定理

lucas定理可避免上述情况。

递归式:

lucas(n,m,p)C(n,m)\%p p为质数),则

lucas(n,m,p)=C(n\%p,m\%p,p)* lucas(n/p,m/p,p)

此处的C(n,m,p)可直接通过逆元计算。

复杂度为\log级。

证明

Code

typedef long long D;
D fac[100001];
void preparefac(D n,D p){
	fac[0]=1;
	for(D i=1;i<=n;i++){
		fac[i]=i*fac[i-1]%p;
	}
}
D qpow(D x,D y,D p){
	D ans=1;
	while(y>0){
		if(y%2)ans=ans*x%p;
		x=x*x%p;
		y/=2;
	}
	return ans;
}
D cal(D x,D y){
	return qpow(x,y-2,y);
}
D Div(D x,D y,D p){
	return x*cal(y,p)%p;
}
D C_(D n,D m,D p){
	if(m>n)return 0;
	return Div(Div(fac[n],fac[m],p),fac[n-m],p);
}
D C(D n,D m,D p){
	if(!m)return 1;
	return C_(n%p,m%p,p)*C(n/p,m/p,p)%p;
}

线性递推求逆元

首先 1^{-1}≡1(\%p)
p=k* i+r
k* i+r≡0(\%p)
等式两边乘 i^{-1}* r^{-1}
k* r^{-1}+i^{-1}≡0(\%p)
\therefore i^{-1}≡-k* r^{-1}(\%p)
\therefore i^{-1}≡-floor(\frac{p}{i})* (p\%i)^{-1}(\%p)

Code

inv[1]=1;
inv[i]=(p-p/i)*inv[p%i]%p;

阶乘逆元

i 的阶乘逆元等于 i-1 的阶乘逆元乘以 i 的逆元。

Code

facinv[i]=facinv[i-1]*inv[i]%p;

CRT

用于求解一元线性同余方程组 x\equiv a_i\pmod{m_i}
过程:

  1. b_i=\prod_{j\neq i}m_j
  2. c_i\equiv b_i^{-1}\pmod{m_i}
  3. ans=\sum_{i=1}^n a_ib_ic_i\pmod{\prod_i m_i}

证明

对于i\in[1,n]ans\equiv a_i+\sum_{j\neq i} a_jb_jc_j\pmod{m_i},由于m_i|b_j(j\neq i)\therefore ans\equiv a_i\pmod{m_i}

exCRT

对于多个方程的情况,考虑将方程两两合并。

对于两个方程的情况x\equiv a_1\pmod{m_1},x\equiv a_2\pmod{m_2}

转换:x=m_1s+a_1=m_2t+a_2 \Rightarrow m_1s-m_2t=a_2-a_1,使用exgcd求解

\gcd(m_1,m_2)\nmid a_2-a_1时无解

高端数论

积性函数

f(xy)=f(x)f(y)(x\perp y)

完全积性函数

f(xy)=f(x)f(y)

欧拉函数

定义

\varphi(n)=\sum_{i=1}^n [i\perp n]

性质

\varphi(p)=p-1(p\text{ is prime})

显然,除了它本身以外的数都和该质数互质。

\varphi(p^k)=p^k-p^{k-1}(p\text{ is prime})

p^k 不互质的数就是 p 的倍数,有 \frac{p^k}{p}=p^{k-1} 个。

\varphi(a*b)=\varphi(a)*\varphi(b)(\gcd(a,b)=1)

S_x=\{ 所有与 x 互质且 \le x 的数 \} 。显然 |S_x|=\varphi(x)
\because \gcd(a,b)=1,
\therefore S_{a*b}S_a,S_b 一一对应。
\therefore |S_{a*b}|=|S_a|*|S_b|,\varphi(a*b)=\varphi(a)*\varphi(b)

\varphi(2*n)=\varphi(n)(n\% 2=1)

\varphi(2)=1 ,易证。

\varphi(n)=\varphi(\frac{n}{p})*p(p|\frac{n}{p})

\varphi(\frac{n}{p})=\frac{n}{p}*\prod (1-\frac{1}{p_i})
\varphi(n)=p*\frac{n}{p}*\prod (1-\frac{1}{p_i})=p*\varphi(\frac{n}{p})

\varphi(n)=\varphi(\frac{n}{p})*(p-1)(p\text{ is prime},p|n,\gcd(p,\frac{n}{p})=1)

\varphi(p)=p-1 ,易证。

\sum_{d|n}\varphi(d)=n

f(n)=\sum_{d|n}\varphi(d)
\gcd(x,y)=1 时, f(x)*f(y)=x\prod_{p_i是x的质因子}(1-\frac{1}{p_i})*y\prod_{p_i是y的质因子}(1-\frac{1}{p_i})=x*y\prod_{p_i是x*y的质因子}(1-\frac{1}{p_i})=f(x*y)
\therefore f(n) 是积性函数。
f(p^k)=\sum_{i=0}^k \varphi(p^i)=p^k
于是我们把 n 分解质因数:
n=\prod p_i^{k_i}
f(n)=\prod f(p_i^{k_i})=\prod p_i^{k_i}=n

公式

\varphi(x)=x\prod (1-\frac{1}{p_i})
p_ix 的第 i 个质因子, x≥2\varphi(1)=1
根据唯一分解定理, x=\prod p_i^{k_i}
\therefore \varphi(x)=\prod \varphi(p_i^{k_i})=\prod (p_i^{k_i}-p_i^{k_i-1})=x\prod (1-\frac{1}{p_i})

其他常用函数

\epsilon(n)=[n=1]

id(n)=n

1(n)=1

\sigma_k(n)=\sum_{d\mid n}d^k

其中\omega(n)表示n的本质不同质因子个数,是一个积性函数。

狄利克雷卷积

(f*g)(n)=\sum_{d\mid n}f(d)g(\frac{n}{d})

例子

\epsilon=\mu*1

\sigma_0=1*1

\sigma=id*1

\varphi=\mu*id

\varphi=\mu*id证明

\varphi*1=id \Rightarrow \varphi*1*\mu=id*\mu \Rightarrow \varphi*\epsilon=\mu*id

莫比乌斯反演

f(n)=\sum_{d\mid n}g(d)\Rightarrow g(n)=\sum_{d\mid n}\mu(d)f(\frac{n}{d})


注:
[1] 在本文中,\%表示取模运算,等价于\text{mod}
[2] floor(x)表示\lfloor x \rfloor
posted @   chc_1234567890  阅读(480)  评论(0编辑  收藏  举报
编辑推荐:
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
阅读排行:
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 《HelloGitHub》第 106 期
· 数据库服务器 SQL Server 版本升级公告
· 深入理解Mybatis分库分表执行原理
· 使用 Dify + LLM 构建精确任务处理应用
点击右上角即可分享
微信分享提示