数论学习笔记

该博客聚焦数论算法,介绍了质数筛法,包括埃氏筛和线性筛;阐述费马小定理、欧拉定理及其相关函数;讲解同余性质、乘法逆元的定义与求法;还涉及线性方程、莫比乌斯反演及Lucas定理,为数论算法学习提供了全面知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

质数筛法

Eratosthenes筛选法

顾名思义就是数学家 Eratosthenes 发明的筛法,简称为埃氏筛。

基本思想

质数的倍数一定不是质数。

实现方法

用一个长度为 N+1N+1N+1 的数组保存信息,000 表示质数,111 表示合数。先假设所有的数都是质数(初始化为 000),从小到大枚举每一个质数 xxx,把 xxx 的倍数都标记为非质数(置为 111)。

如何枚举质数 xxx 呢?从小到大扫描到 xxx 时,若 xxx 未被标记,则它不能被 2∼x−12\sim x-12x1 之间的任何数整除,则 xxx 为质数。

举个例子:

2,3,4,5,6,7,8,9,10,11,12,⋯⇓2,3,5,7,11,⋯⇓⋯ \begin{aligned} &2,3,4,5,6,7,8,9,10,11,12,\cdots\\ &\Downarrow\\ &2,3,5,7,11,\cdots\\ &\Downarrow\\ &\cdots \end{aligned} 2,3,4,5,6,7,8,9,10,11,12,2,3,5,7,11,

可以发现,存在重复标记的耗时行为。实际上,小于 x2x^2x2xxx 的倍数在扫描更小的数时就已经被标记过了。因此,可以优化一下,对于每个 xxx,把大于等于 x2x^2x2xxx 的倍数标记为合数即可。

代码如下:

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

算法的时间复杂度为 O(nlog⁡log⁡n)O(n\log\log n)O(nloglogn),效率非常接近于线性。时间复杂度的证明非常复杂,本蒟蒻也不太会,所以不证了

线性筛法

即使在优化后,埃氏筛仍然会重复标记合数。举个栗子,121212 既会被 222 标记又会被 333 标记,其根本原因是算法不能确定唯一的产生 121212 的方式。

所以,我们只要保证合数被它的最小质因数筛去就好啦!时间复杂度为 O(n)O(n)O(n)

代码如下:

int v[maxn],prime[maxn];
void primes(int n)
{
    memset(v,0,sizeof(v));//存储最小质因子
    int m=0;//质数数量
    for(int i=2;i<=n;i++)
    {
        if(v[i]==0)
            v[i]=i,prime[++m]=i;
        for(int j=1;j<=m;j++)
        {
            //i有比prime[j]更小的质因子或者要筛的数超出n的范围
            if(prime[j]>v[i]||prime[j]*i>n) break;
            v[i*prime[j]]=prime[j];
        }
    }
    for(int i=1;i<=m;i++)
        cout<<prime[i]<<endl;
}

费马小定理、欧拉定理

费马小定理

如果 ppp 是一个质数,而整数 aaa 不是 ppp 的倍数,则有 ap−1=1(modp)a^{p-1}=1\pmod pap1=1(modp)

一般情况:ap=a(modp)a^p=a \pmod pap=a(modp)

欧拉定理

欧拉函数

对正整数 nnn,欧拉函数是小于等于 nnn 的数中与 nnn 互质的数的数目。

引理 1
  1. 如果 nnn 为某一个素数 ppp,则:φ(p)=p−1\varphi(p)=p-1φ(p)=p1
  2. 如果 nnn 为某一个素数的 ppp 的幂次 pnp^npn,则:φ(pn)=(p−1)×pn−1\varphi(p^n)=(p-1) \times p^{n-1}φ(pn)=(p1)×pn1
  3. 如果 nnn 为任意两个互质的数 a,ba,ba,b 的积,则:φ(a×b)=φ(a)φ(b)\varphi(a\times b)=\varphi(a)\varphi(b)φ(a×b)=φ(a)φ(b)
引理 2

n=p1a1×p2a2×⋅⋅⋅×pkakn=p_1^{a_1}\times p_2^{a_2}\times···\times p_k^{a_k}n=p1a1×p2a2×⋅⋅⋅×pkak 为正整数 nnn 的素数幂乘积表达式,则:φ(n)=n×(1−1p1)×(1−1p2)×⋅⋅⋅×(1−1pk)\varphi(n)=n\times(1-\dfrac{1}{p_1})\times(1-\dfrac{1}{p_2})\times···\times(1-\dfrac{1}{p_k})φ(n)=n×(1p11)×(1p21)×⋅⋅⋅×(1pk1)

欧拉定理

aaammm 互质,则 aφ(m)=1(modm)a^{\varphi(m)}=1\pmod maφ(m)=1(modm)

同余性质

前置芝士:费马小定理、欧拉定理

整数 a,b,ca,b,ca,b,c,自然数 m,nm,nm,n,模 mmm

  • 自反性:a≡b(modm)a\equiv b\pmod mab(modm)

  • 对称性:若 a≡b(modm)a\equiv b\pmod mab(modm),则 b≡a(modm)b\equiv a\pmod mba(modm)

  • 传递性:若 a≡b(modm),b≡c(modm)a\equiv b\pmod m,b\equiv c\pmod mab(modm),bc(modm),则 a≡c(modm)a\equiv c\pmod mac(modm)

  • 同加性:若 a≡b(modm)a\equiv b\pmod mab(modm),则 a+c≡b+c(modm)a+c\equiv b+c\pmod ma+cb+c(modm)

  • 同乘性:若 a≡b(modm)a\equiv b\pmod mab(modm),则 ac≡bc(modm)ac\equiv bc\pmod macbc(modm)

    一般情况,若 a≡b(modm),c≡d(modm)a\equiv b\pmod m,c\equiv d\pmod mab(modm),cd(modm),则 ac≡bd(modm)ac\equiv bd\pmod macbd(modm)

  • 同幂性:若 a≡b(modm)a\equiv b\pmod mab(modm),则 an≡bn(modm)a^n\equiv b^n\pmod manbn(modm)

  • a mod p=x,a mod q=xa\bmod p=x,a\bmod q=xamodp=x,amodq=xp,qp,qp,q 互质,则 a mod pq=xa\bmod pq=xamodpq=x

乘法逆元

定义

ax=1(modb)ax=1 \pmod bax=1(modb)a,ba,ba,b 互质,则称 xxxaaa 的逆元,记为 a−1a^{-1}a1

作用

逆元可以在计算 ta mod b\boxed{\dfrac{t}{a}\bmod b}atmodb 时,转化为 t×a−1 mod b\boxed{t\times a^{-1}\bmod b}t×a1modb

求法

扩展欧几里得算法

根据逆元的定义,可转化为 ax+by=1ax+by=1ax+by=1,用扩展欧几里得算法求解。时间复杂度 O(log⁡b)O(\log b)O(logb)

友情赠送代码:

void exgcd(int a,int b,int c,int &x,int &y)
{
    if(a==0)
    {
        x=0;y=c/b;
        return;
    }
    else
    {
        int tx,ty;
        exgcd(b%a,a,tx,ty),x=ty-(b/a)*tx,y=tx;
        return;
    }
}
线性算法

前置芝士:1−1≡1(modp)1^{-1}\equiv1\pmod p111(modp)

p=k×i+r,r<i,1<i<pp=k\times i+r,r<i,1<i<pp=k×i+r,r<i,1<i<p,则:k×i+r≡0(modp)k\times i+r\equiv 0\pmod pk×i+r0(modp)

两边同时乘 i−1,r−1i^{-1},r^{-1}i1,r1 就会得到:

k×r−1+i−1≡0i−1≡−k×r−1i−1≡−[pi]×(p mod i)−1 \begin{aligned} k\times r^{-1}+i^{-1}&\equiv0\\ i^{-1}&\equiv-k\times r^{-1}\\ i^{-1}&\equiv-\left[\dfrac{p}{i}\right]\times (p\bmod i)^{-1}\\ \end{aligned} k×r1+i1i1i10k×r1[ip]×(pmodi)1

于是,就可以递归求逆元啦!代码只有一行!

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

这种方法可以在 Θ(log⁡2p)\Theta(\log_2p)Θ(log2p)(众所周知 Θ\ThetaΘ 表示时间复杂度更准确 qwq)的时间内求出单个数逆元。

线性方程

前置芝士:人人都会的辗转相除法(∀a,b∈N,b≠0,gcd⁡(a,b)=gcd⁡(b,a mod b)\forall a,b\in \mathbb{N},b\neq0,\gcd(a,b)=\gcd(b,a\bmod b)a,bN,b=0,gcd(a,b)=gcd(b,amodb)

扩展欧几里得算法

定理 1

a≠0,b≠0a\neq0,b\neq0a=0,b=0,存在整数x、yx、yxy,使得 ax+by=gcd⁡(a,b)ax+by=\gcd(a,b)ax+by=gcd(a,b)

证明

在欧几里得算法的最后一步,当 b=0b=0b=0 时,gcd⁡(a,b)=a\gcd(a,b)=agcd(a,b)=a。因为 1×a+0×0=a1\times a+0\times 0=a1×a+0×0=a,所以 ax+by=gcd⁡(a,b)ax+by=\gcd(a,b)ax+by=gcd(a,b) 有一组解为x=1,y=0x=1,y=0x=1,y=0

b≠0b\neq0b=0 时,递归求 gcd⁡(b,a mod b)\gcd(b,a\bmod b)gcd(b,amodb),假设存在一组整数解 x′,y′x',y'x,y,满足 bx′+(a mod b)y′=gcd⁡(b,a mod b)=gcd⁡(a,b)bx'+(a\bmod b)y'=\gcd(b,a\bmod b)=\gcd(a,b)bx+(amodb)y=gcd(b,amodb)=gcd(a,b),那么可以推出:

bx′+(a−⌊ab⌋×b)y′=gcd⁡(a,b)ay′+b(x′−⌊ab⌋y′)=gcd⁡(a,b) \begin{aligned} &bx'+(a-\lfloor\dfrac{a}{b}\rfloor\times b)y'=\gcd(a,b)\\ &ay'+b(x'-\lfloor\dfrac{a}{b}\rfloor y')=\gcd(a,b) \end{aligned} bx+(aba×b)y=gcd(a,b)ay+b(xbay)=gcd(a,b)

于是乎,令 x=y′,y=x′−⌊ab⌋y′x=y',y=x'-\lfloor\dfrac{a}{b}\rfloor y'x=y,y=xbay

代码如下:

(对于 & 取地址符的问题,如果不加,相当于把传进去的参量复制了一份进入到函数中,不会影响主函数里的那个值;如果加取地址符相当于直接把参量扔进去了)

void exgcd(int a,int b,int &g,int &x,int &y)//g是gcd(a,b)
{
    if(!b) x=1,y=0,g=a;
    else exgcd(b,a%b,g,y,x),y-=x
}
定理 2

对于不定方程 ax+by=cax+by=cax+by=c,当且仅当 gcd⁡(a,b)=c\gcd(a,b)=cgcd(a,b)=c 时,方程有整数解。

莫比乌斯反演

莫比乌斯函数

前置芝士:质数筛选

定义

设正整数 NNN 按照算数基本定理分解质因数为 p1c1p2c2⋯pmcmp_1^{c_1}p_2^{c^2}\cdots p_m^{c_m}p1c1p2c2pmcm,定义函数

μ(N)={0∃i∈[1,m],ci>11m≡0(mod2),∀i∈[1,m],ci=1−1m≡1(mod2),∀i∈[1,m],ci=1 \mu(N)= \begin{cases} 0&\exists i\in[1,m],c_i>1\\ 1&m\equiv0\pmod2,\forall i\in[1,m],c_i=1\\ -1&m\equiv1\pmod2,\forall i\in[1,m],c_i=1 \end{cases} μ(N)=011i[1,m],ci>1m0(mod2),i[1,m],ci=1m1(mod2),i[1,m],ci=1

μ(n)\mu(n)μ(n) 即为莫比乌斯函数。

NNN 包含相等的质因子时,μ(n)=0\mu(n)=0μ(n)=0。当 NNN 的所有质因子各不相等时,若 NNN 有偶数个质因子,μ(N)=1\mu(N)=1μ(N)=1;若 NNN 有奇数个质因子,μ(N)=−1\mu(N)=-1μ(N)=1

求法

若只求一项莫比乌斯函数,分解质因数即可。

若求 1∼N1\sim N1N 的每一项莫比乌斯函数,可以使用埃氏筛。先把所以 μ\muμ 初始化为 111。对于筛出的每一个质数 ppp,令 μ(p)=−1\mu(p)=-1μ(p)=1,扫描 ppp 的倍数,检查 xxx 能否被 ppp 整除。若能,则令 μ(x)=0\mu(x)=0μ(x)=0;否则,令 μ(x)=−μ(x)\mu(x)=-\mu(x)μ(x)=μ(x)

代码如下:

  • 埃氏筛

    for(int i=1;i<=n;i++) mu[i]=1,v[i]=0;
    for(int i=2;i<=n;i++)
    {
        if(v[i]) continue;
        mu[i]=-1;
        for(int j=2*i;j<=n;j+=i)
        {
            v[j]=1;
            if((j/i)%i==0) mu[j]=0;
            else mu[j]*=-1;
        }
    }
    
  • 线性筛

    for(int i=2;i<=n;++i)
    {
        if(!vis[i]) p[++tot]=i,mu[i]=-1;
        for(int j=1;j<=tot&&1ll*p[j]*i<=n;++j)
        {
            int now=i*p[j];
            vis[now]=1;
            if(i%p[j]==0) mu[now]=0;
            else {mu[now]=-mu[i];break}
        }
    }
    
性质
  1. 对任意正整数 nnn 有:∑d∣nμ(d)={1n=10n>1\sum\limits_{d|n}\mu(d)=\begin{cases}1&n=1\\0&n>1\end{cases}dnμ(d)={10n=1n>1

  2. 对任意正整数 nnn 有:∑d∣nμ(d)d=φ(n)n\sum\limits_{d|n}\dfrac{\mu(d)}{d}=\dfrac{\varphi(n)}{n}dndμ(d)=nφ(n)

莫比乌斯反演

莫比乌斯反演,可以简化运算。

定理:F(n)F(n)F(n)f(n)f(n)f(n) 是定义在非负整数集合中的两个函数,F(n)=∑d∣nf(d)F(n)=\sum\limits_{d|n}f(d)F(n)=dnf(d),那么
f(n)=∑d∣nμ(d)F(nd) f(n)=\sum_{d|n}\mu(d)F(\dfrac{n}{d}) f(n)=dnμ(d)F(dn)

Lucas 定理

Lucas 定理主要用于解决大组合数取模的问题。注意这里的模数 ppp 不能太大,一般小于 10510^5105

ppp 是质数,则对于任意整数 1≤m≤n1\leq m\leq n1mn,有:
Cnm=Cn mod pm mod p×C⌊n/p⌋⌊m/p⌋(modp) C_n^m=C_{n\bmod p}^{m\bmod p}\times C_{\lfloor n/p\rfloor}^{\lfloor m/p\rfloor}\pmod p Cnm=Cnmodpmmodp×Cn/pm/p(modp)
相当于把 nnnmmm 表示为 ppp 进制数,将 ppp 进制下的每一位数计算组合数相乘。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值