数论基础

前言

长文警告
这是暑假的一个课件,突然想起来,就发出来了。
全部有关的习题的题单:https://www.luogu.com.cn/training/184246
由于 BSGS 和 拉格朗日插值 是后面临时加的,所以顺序被调到了前面,而且没有习题。
以下为原文(略有改变)


数论基础

————————by jiangtaizhe001

首先默认讨论的数全是整数。

整除、取余、同余的定义

a=bq+r,其中 q0,0r<q,则称 amodq=r
如果 r=0amodb=0 那么称 q 整除 a,记作 qa,此时 qa 的约数,aq 的倍数。
如果 r0amodp0,那么称 q 不整除 a,记作 qa
如果 amodp=bmodp,那么称 a,bp 同余,记作 ab(modp)

整除、同余的性质

ab|a||b|abkakbab,bcac
ab(modp)p(ab)
ab(modp)a+cb+c(modp)
ab(modp)acbc(modp)
ab(modp)anbn(modp)

质数与合数

将全体正整数按照约数个数分类可以分为质数(又称素数)、合数和 1
质数有 2 个约数,合数的约数数量 21 只有一个约数,1 既不是质数也不是合数。

质数的数量是无限的。
证明:
假设质数数量有限,那么设有 n 个质数,分别为 p1,p2,,pn
考虑 t=(i=1npi)+1
如果这个数字是质数,那么显然 t>pi,假设不成立。
如果这个数字不是质数,我们发现 pi 都不是 t 的约数,假设不成立。
所以推出原假设矛盾,故质数有无数个。

我们一般用 π(n) 代表小于等于 n 的质数个数。
n 比较大的时候我们可以认为 π(n)xlnx

筛法

一个一个判断(筛至根号):O(nn)
埃拉托斯特尼筛法:O(nloglogn)
欧拉筛(线性筛):O(n)

当然埃氏筛可以使用 bitset 进行优化,欧拉筛还可以筛大部分积性函数。

欧拉函数

定义

φ(n) 代表 小于等于 n 并且与 n 互质的正整数数的个数。

计算

n 进行质因数分解得到 n=i=1kpiai(ai>0)
根据欧拉函数定义可得

φ(n)=n×i=1k(11pi)

证明略。

gcd(a,b)=1φ(a)×φ(b)=φ(a×b)(欧拉函数是积性函数,可以用上面的结论证明)

根据以上结论可以在 O(n) 时间内求出 φ(n),可以利用线性筛在 O(n) 的时间内求出 φ(1),φ(2),,φ(n)

欧拉定理与费马小定理

gcd(a,p)=1 时,aφ(p)1(modp)
证明:
根据欧拉函数的定义,满足 1rp 并且 gcd(r,p)=1 的数字 r 的数量为 φ(p) 个,记作 r1,r2,,rφ(p),显然 ri 两两模 p 不同余。
不难得到对于任意的 igcd(ari,p)=1
假设存在 1i<jm 使得 ariarj(modp) 成立,由于 gcd(a,p)=1 所以 rirj(modp),所以假设不成立,也就是说 ari 两两模 p 不同余。
所以说对于任意的 1im,存在且仅存在一个 j 使得 riarj(modp),1jm
也就是说

i=1φ(m)rii=1φ(m)ari(modp)

由于 gcd(ri,p)=1,所以可以将相同部分的 i=1φ(p)ri 约去。
得到

aφ(p)1(modp)

p 为质数的时候,φ(p)=p1,那么就可以得到

ap11(modp)

这就是费马小定理。

gcd、exgcd

gcd

gcd(a,b)=gcd(b,amodb)

证明如下:
a=bq+r 并且 0r<b,显然 r=amodb
dadbd 就是 a,b 的公约数,
a=bq+rad=q×bd+rd
也就是 rd=adq×bd
因为 da,db,所以 ad,q×bd 都是整数,
所以 rd 也是整数,d 也是 b,amodb 的公约数,
同理我们也可以设 ebeamodb
同理可以证明 e 也是 a,b 的公约数。
换句话说, a,b 的公约数都是 b,amodb 的公约数,b,amodb 的公约数也都是 a,b 的公约数,
也就是说 a,bb,amodb 的公约数都相同,那么它们的最大公约数也都相等,也就是 gcd(a,b)=gcd(b,amodb)

根据这个结论我们可以递归在 O(logn) 的时间内求出两个数字的最大公约数,当两个数字为斐波那切数列的相邻两项的时候为最坏情况。这个算法被称为欧几里得辗转相除法。

裴蜀定理

裴蜀定理(又称贝祖定理):
如果gcd(a,b)c,那么关于 x,y 的一元二次方程 ax+by=c 有解。
可以根据 exgcd 辗转相除然后回带的过程来证明,这里就略去证明。

exgcd

找到关于 x,y 的一元二次方程 ax+by=gcd(a,b) 的一组解
根据 gcd 的过程,将原方程转化为

bx+(amodb)y=gcd(b,amodb)

因为 gcd(a,b)=gcd(b,amodb),所以联立上面两式可得

ax+by=bx+(amodb)y

根据 amodb=aab×b 带入化简可得

(xy)a+(yx+ab×y)b=0

此时我们可以得到

{x=yy=xab×y

这样可以递归求解,递归边界就是 b=0,返回 (x,y)=(1,0) 即可。

当我们有一组解 x=x,y=y 的时候,就可以得出通解:

{x=x+kbgcd(a,b)y=ykagcd(a,b)

其中 k 为任意整数。

更一般的,对于任意的一个关于 x,y 的二元一次方程 ax+by=c
如果 gcd(a,b)c 那么我们先解出方程 ax+by=gcd(a,b) 的一组特解 x,y,设 m=cgcd(a,b),不难得出通解:

{x=m×x+kbgcd(a,b)y=m×ykagcd(a,b)

应用:解线性同余方程

考虑关于 x 的以下方程:

axb(modp)

根据同余的定义可得
存在一个正整数 k 满足

ax=kp+b

也就是

axpk=b

这就是一个关于 x,k 的一个一元二次方程了,直接使用 exgcd 即可。

乘法逆元

定义

对于整数 x,如果 gcd(a,p)=1,那么不难证明存在一个 0a<p 使得 ax1(modp),那么称 a 在模 p 下的逆元为 x,记作 1aa1

计算

方法一:快速幂
p 为质数的时候,可得

ap11(modp)

所以

a1ap2(modp)

方法二:exgcd
其实就是解这个线性同余方程即可。

方法三:线性逆元线性求
考虑在 O(n) 的时间内求出 1,2,,n 所有数字模 p 的逆元。(下面的逆元默认为模 p 意义下)
显然 1 的逆元为 1,然后假设我们已经求出 1,2,3,,a1 的逆元,现在求 a 的逆元。
p=aq+r 其中 0r<a,显然 q=pa,r=pmoda
显然

aq+r0(modp)

移项得

aqr(modp)

两边同时乘上 a1r1,得

a1q×r1(modp)

也就是

a1pa×(pmoda)(modp)

这样就可以 O(n) 求了。

方法四:阶乘逆元线性求
在做组合题的时候,根据公式 Cnm=n!m!×(nm)!,我们发现只需要预处理出 n!n!1 就可以 O(1) 求组合数在模一个大质数的结果了。
其实不难发现

(n+1)!1×(n+1)n!1(modp)

所以只需要反着刷一遍就好,时间复杂度是 O(n)

中国剩余定理

中国剩余定理 (Chinese Remainder Theorem) 简称CRT。

CRT

考虑解以下关于 x 的方程:

{xa1(modm1)xa2(modm2)xa3(modm3)xan(modmn)

保证 mi 两两互质。

我们考虑如何解这个方程。
我们考虑对于每个 i 找到一个 ci,使得

ci1(modmi)(1)ci0(modmj)(ij)(2)

这样显然解就是

xi=1naici(modi=1nmi)

考虑如何得到 ci,显然 ci 一定是 Mi=j=1,jinmj 的倍数。
这样就已经满足 (2) 式了,接下来考虑如何满足 (1) 式。

注意到求出 Mi 在模 mi 意义下的逆元 Mi1,令 ci=Mi×Mi1 就可以了。由于满足 mi 两两互质,所以逆元肯定存在。

总结中国剩余定理的步骤:

  1. 计算 M=i=1nmi
  2. 对于所有的 1in 计算 Mi=Mmi
  3. Mi1Mi 在模 mi 意义下的逆元
  4. 方程的解为

xi=1naiMiMi1(modM)

证明略。

exCRT

更一般的,如果不保证 mi 两两互质,是否能够以上方法得到通解呢?
这是我们发现这个 ci 不一定能够找到,因为 Mi 在模 mi 意义下的逆元不一定存在。
所以我们需要寻找另外的解法。

我们简化一下问题,我们可以先考虑两个方程的情况,然后两两合并方程即可。

{xa1(modm1)xa2(modm2)

根据前面的做法,我们可以把同余方程转化为一元二次不定方程,得到

{x=m1q+a1x=m2p+a2

两式相减可得

m1qm2p=a2a1

利用 exgcd 解出这个关于 p,q 的方程,如果无解就说明原方程无解。
这样就可以解出方程,解为

xa1q+b1(modlcm(m1,m2))

或者是

xa2p+b2(modlcm(m1,m2))

这样复杂度也是 O(nlogmi) 的,但是稍微会难写一点。

整除分块

整除分块又叫数论分块。

引-UVA11526 H(n)

求出

i=1nni

多组数据,0n2311,数据组数 T1000
显然直接枚举是不行的。我们可以令 f(x)=ni,先令 n=10,作出函数 y=f(x) 的图像。
graph1.png

我们发现,虽然自变量 x 的取值有 10 种,但是 f(x) 的取值只有 5 种。并且当 n=100 的时候,x 的取值又 100 种,但是 f(x) 的取值只有 19 种。

不难发现以下结论:

nN+,|{niiN+,in}|2n

证明:
in 时,ni 最多 n 个数字。
n<in 时,1nin,最多有 n 个数字。
因此最多只有 2n 个数字。

所以说,我们可以能够预处理出每个使 f(x) 相同的区间来更快地计算答案,这样的时间复杂度是 O(n) 的,提高了不少。

结论

对于一个数字 n,如果 ni=nj 成立,那么满足 i<jn 最大的 jnni

结论证明

引理

引理:

a,b,cZ,abc0,abc=abc

证明:

ab=ab+r,0r<1

那么

abc=(ab+r)×1c=abc+rc=abc

结论证明

首先显然有

nini

所以

nnninnnini=ni

所以说最大的 j 满足 ni=njnni

实例

假设我们需要计算式子大概为类似 i=1nf(i)ni 的形式并且可以得到 f(i) 的前缀和 s(i),那么我们可以在 O(n) 的时间内求出这个式子。(假设 s(i) 调用复杂度为 O(1)
代码大致如下:

int l=1,r,sum=0;
while(l<=n){
r=n/(n/l);
sum+=n/l*(s(r)-s(l-1));
l=r+1;
}

多维数论分块

有些时候式子可能会更加复杂,大概是类似于 i=1nf(i)j=1maji,此时 i 所在的右端点就会变成 minj=1mnjnji。当然其实 n=2 的情况最常见。

应用

数论分块更多结合莫比乌斯反演来降低时间复杂度。

卢卡斯定理

卢卡斯定理用于求出当模数为一个比较小的质数的时候 (nm) 的值。
这里就给个公式吧,其实是因为我大不会证明。

(nm)(n/pm/p)×(nmodpmmodp)(modp)

其中 p 为质数。
这时我们只需要预处理出 1!,2!,,(p1)! 这些数字模 p 的值以及模 p 意义下的逆元就可以通过递归求出任意的 (nm) 了。空间复杂度 O(p),时间复杂度为 O(p+logpn)
p 不为质数的时候就需要用扩展卢卡斯定理来求了,这里不写出。

BSGS

基础篇

找到方程

axb(modp)

的最小整数解,其中 gcd(a,p)=11a,p1012

首先根据欧拉定理,我们知道

axaxmodφ(p)(modp)

由于 φ(p)<p,所以如果方程有解,那么在 [0,p] 内肯定会有解。

直接枚举显然是不行的,我们发现因为 gcd(a,p)=1,所以 a 的任意次方在模 p 意义下都存在逆元,我们是否能够使用这一个性质来解这个方程呢?

x=Ap+B
这样就有

aAp+Bb(modp)

这样不难得到

aApaBb(modp)

我们可以对于所有的 0Bp 求出 aBb 在模 p 下的值,放到一个哈希表里面,然后枚举 A 检验就可以了。
时间复杂度 O(p)

扩展篇

如果 gcd(a,p)1,我们应该怎么办呢?
我们发现这时我们对于所有的 0Bp,我们不一定可以找到 aB 在模 p 意义下的逆元,所以我们试图通过一些方法来转化。
众所周知,acbc(modpc)ab(modp)
我们可以利用这个性质来转化原式。

t1=gcd(a,p)
这样我们就得到

at1×ax1bt1(modpt1)

继续令 t2=gcd(a,pt1),得到

a2t1t2×ax2bt1t2(modpt1t2)

接下来令 t3=gcd(a,pt1t2),得到

a3t1t2t3×ax3bt1t2t3(modpt1t2t3)

我们可以继续进行这样的操作若干次,直到 gcd(a,pi=1nti)=1,得到

ani=1nti×axnbi=1nti(modpi=1nti)

这样就可以转化为 BSGS 求解了。

不过要注意两个细节:

  1. 解可能小于 n,所以需要是否存在小于 n 的解。
  2. 如果 i=1ntib 那么无解。

显然 nO(logp) 级别,所以时间复杂度还是 O(p)

拉格朗日插值

给定一个 n1 次函数 f(x) ,已知

{f(x1)=y1f(x2)=y2f(xn)=yn

现在求出 f(k)k 为任意值。

显然我们可以通过差分、高斯消元来求出 f(x) 的表达式,进一步求出 f(k),但是这样的复杂度都是 O(n3) 的,能否找到更优的解法呢?

我们可以试试能不能 直接构造f(x) 的表达式。

考虑先构造 n 个函数 f1(x),f2(x),,fn(x) ,使得

{fi(xi)=yifi(xj)=0(ij)

显然这样就能得到 f(x)=i=1nfi(x)

考虑如何构造 fi(x)
显然 fi(x) 存在因子

j=1,jin(xxj)

这样就可以设

fi(x)=aj=1,jin(xxj)

带入点 (xi,yi) 就可以得到

fi(x)=yij=1,jinxxjxixj

所以

f(x)=i=1nyij=1,jinxxjxixj

这样虽然求 f(x) 表达式仍然是 O(n3),但是如果直接单点求值的话就是 O(n2) 的了。

习题选讲

P7960 [NOIP2021] 报数

两个人玩报数游戏,如果一个数字存在一个约数在十进制下有数字 7,那么这个数字不能被报出。上一个人报出的数字为 x,现在求下一个报出的数字为多少,如果上一个人报出的数字不合法输出 1
多组数据,数据组数 T2×105,1x107

Solution
x107,所以其实不需要使用线性筛,根据前面游戏的规则发现埃氏筛更加使用,所以直接用埃氏筛筛出所有能被报出的数字即可,注意不要筛到 107 就停。时间复杂度 O(nloglogn+T)。(其实会小一点)

P2158 [SDOI2008] 仪仗队

有一个 N×N 的方阵,现在你在方阵的左下角。如果方阵排整齐,求你能看到几个同学。N4×104

Solution
我会莫比乌斯反演!
不难发现答案就是 i=0N1j=0N1[gcd(i,j)=1]

考虑以下内容帮助我们解题:
gcd 的两个性质:gcd(a,b)=gcd(b,a)gcd(0,i)=gcd(i,0)=i
欧拉函数的定义:φ(n)=i=1n[gcd(i,n)=1]
不难得到:

i=0N1j=0N1[gcd(i,j)=1]=i=0N1j=0i1[gcd(i,j)=1]+i=0N1j=i+1N1[gcd(i,j)=1]+i=0N1[gcd(i,i)=1]=2×i=0N1j=0i1[gcd(i,j)=1]+1=2×i=1N1φ(i)+1

跑个线性筛就可以了。时间复杂度 O(N)

P2398 GCD SUM

i=1nj=1ngcd(i,j)

其中 n105

Solution
我会莫比乌斯反演!

i=1nj=1ngcd(i,j)=d=1ni=1nj=1n[gcd(i,j)=d]×d=d=1ni=1n/dj=1n/d[gcd(i,j)=1]×d=d=1n(2d×i=1n/d(φ(i)1))(这步推导详见上一题)

所以只需要跑个线性筛,然后预处理出 φ(n) 的前缀和就可以了。时间复杂度 O(n)

P4774 [NOI2018] 屠龙勇士:

按照编号 1n 顺序杀掉 n 条巨龙,每条巨龙拥有一个初始的生命值 ai 。并且巨龙会在生命值为负的时候恢复生命值 pi ,当生命值 恰好0 时它才会死去。
最初你拥有 m 把攻击力已知的剑,每次可以选择一把剑来面对巨龙,当杀死巨龙后这把剑就会消失,同事玩家会获得全新的一把剑。
每次面对巨龙时,默认会选择当前拥有的,攻击力不高于巨龙初始生命值中攻击力最大的一把剑作为武器。如果没有这样的剑,则选择攻击力最低 的一把剑作为武器,设攻击力为 ATK
每次面对每条巨龙,它都会使用上一步中选择的剑攻击巨龙固定的 x 次,使巨龙的生命值减少 x×ATK
之后,巨龙会不断恢复 pi 的生命值。若在使用恢复能力前或某一次恢复后其生命值为 0 ,则巨龙死亡,开始杀掉下一条巨龙。
现在需要求出题目中 x 的最小值,若最小值不存在输出 1

数据范围: n105ai1012lcm(pi)1012,所有武器的攻击力 106

Solution
首先使用平衡树(或者是 multiset)求出打每一只巨龙所用的剑的伤害,显然打每一只巨龙所用的剑的伤害是一个固定的值。设打第 i 只巨龙所用的剑的伤害为 atki
然后就相当于解下面的同余方程组:

{atk1xa1(modp1)atk2xa2(modp2)atknxan(modpn)

方法一
显然每一个方程都是线性同余方程,所以可以解出这 n 个方程,就可以直接使用 exCRT 进行求解。
方法二
还是考虑两两合并方程,然后转化为一元二次不定方程求解。

P2480 [SDOI2010]古代猪文

求出

gdnCnkmod999911659

其中 n,g109

Solution
首先发现 999911659 为一个质数,所以根据欧拉定理或费马小定理可以得到所求式子就是

gdnCnkmod9999611658mod999911659

此时重点就在于求出

dnCnkmod9999611658

枚举 kn 显然是 O(n) 的时间复杂度,但是我们发现 9999611658 不是质数,所以通过求出阶乘及阶乘逆元在模 999611658 的值来求组合数是不可行的,因为逆元不一定存在。
但是我们考虑到 9999611658=2×3×4679×35617,每一个质因数的次数都为 1,所以我们可以利用卢卡斯定理求出这个式子在模 2,3,4679,35617 下的值,然后使用 CRT 合并答案即可。

这也是 CRT 非常重要的一个用途之一。

P2261 [CQOI2007]余数求和

求出

i=1nkmodi

其中 1n,k109

i=1nkmodi=i=1n(kki×i)=n×ki=1n(ki×i)

直接整除分块就可以了。
注意在代码中 k/(k/i)i>k 的时候会因为除数为 0 RE 掉,需要特判。

CF 数论题目选讲

CF1458A

题目大意:
给定一个长度为 n 的数组 a 和一个长度为 m 的数组 b
现在对于每一个 1jm,求出 gcd(a1+bj,a2+bj,,an+bj)
1n,m1051ai,bi1018

Solution
首先 n=1 的时候特判掉。
根据辗转相除可以知道 gcd(a,b)=gcd(a,ba)
所以我们可以利用这个东西把 bj 这一个变动的项消去,只剩下一个。
原式转化为 gcd(a2a1,a3a2,,anan1,an+bj),直接预处理出除掉最后一项的 gcd 即可。
时间复杂度 O(nlogai+mlogbi)

CF1513D

题目大意:
给定一个长度为 n 的序列 a 和一个数字 p
如果 gcd(ai,ai+1,,aj)=min(ai,ai+1,,aj),那么就在 i,j 之间连接一条边权为 min(ai,ai+1,,aj) 的边。同时 i,i+1 两个点之间会有一条边权为 p 的边。
2n2×1051ai,p109

Solution
显然我们发现:如果序列 ai,ai+1,,aj 中最小值为 k,并且所有数字都是 k 的倍数,那么这些点都是联通的,边权为 k
所以只需要判断一下满足 gcd(ai,ai+1,,aj)=min(ai,ai+1,,aj) 的所有极大区间 [i,j] 即可。
具体做法是找到所有比 p 小的 ai,然后向两边扩展到极大,把这一段覆盖掉,如果遇到已经被覆盖的就不需要覆盖了。注意如果一个点从左边被覆盖了,还能从右边覆盖一次。
时间复杂度 O(nlogn)

CF1665D

交互题,你需要猜出一个数字 x
每次你可以给出 a,b,然后你会得到 gcd(x+a,x+b) 的值,你最多可以进行这样的操作 30 次。
1x1091a,b2×109

Solution
显然 gcd(x+a,x+b)=gcd(x+a,ba)
这样我们就可以猜出 x 在二进制下的每一位。

我们从低位到高位猜,假设现在猜的是从右往左第 i 位,那么我们现在就已经知道了右边 i1 位,这些位的数值的和记作 y,令 a=2i1yb=2i+2i1y。假设返回的数是 m。 如果 m=2i,也就是说,在第 i 位加上了 1 会产生进位,那么这一位就是 1,反之这一位就是 0
这样刚好需要猜 30 次。

但是有没有更加优秀的做法呢?

由于 gcd(x+a,x+b)=gcd(x+a,ba),所以 (ba)gcd(x+a,x+b)(ba)(x+a)

考虑构造一个序列 t,使序列 t 中的数字两两互质,并且这些数字尽可能小,令 a=t109a2×109

m=tmax,枚举 i1m,询问得到 gcd(x+a+i,x+i)=gcd(x+i,a) 的值。

如果 tigcd(x+i,a),那么 tix+a+i,我们就能得到 xi(modti)。然后直接使用中国剩余定理合并答案,由于 x109a2×109,所以答案只有一种可能。

t={4,5,7,9,11,13,17,19,23},此时满足条件。
这样只需要询问 23 次。

但是我们发现,枚举 i123 的时候肯定都会得到 x 对于 t 中任意一个元素取模的答案,所以如果在前 22 次的猜测中都没有得到答案,那么肯定在 i=23 的时候能得到答案。
所以这样只需要询问 22 次。

posted @   jiangtaizhe001  阅读(92)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示