数论分享

数论选讲

--数论是数学的皇后--

bg right


写在废话之前

HL 集训的时候,某场模拟赛 T2 放了一个欧拉函数相关的题目,然后当场比赛获得了 \(100\)pts \(+0\)pts \(+0\)pts \(+0\)pts \(=100\) pts 的优异成绩。

细说这场模拟赛的的感受的话,可能云落能讲一个多小时,显然时间并不应该被消耗在这个上面。

不过云落还是对 T2 的欧拉函数耿耿于怀,所以有了后面的数论专项突击,也促成了今天的数论分享。


废话

根据过往云落学习数论的经验来看,这个学习过程是相当枯燥乏味的。反正如果诸位有数学公式恐惧症的话,不建议一次性食用过多。

下一张 PPT 会展示目录,难度是升序排序的,这边建议诸位根据自身情况,选择性或者有方法地听(不建议直接 \(z^{z^z}\))。

知识点基本上会很快过掉,如果需要知识点讲解建议出门左转去 oi.wiki 查阅资料。

里面的例题都是云落做过或者口胡过的好题,拿出来讲解。

云落年岁不小了,剩余的时间需要云落去争分夺秒了。所以云落组织了这次分享是带有很大私心的。在准备的过程中,云落获益良多,也希望可以收益最大化,把这些寄存在云落脑子里的东西展示出来。所以云落希望可以在数论这个方面,邀诸位共赏。

废话结束,正片开始。


目录

  • 基础知识

  • 数论分块

  • 筛法与欧拉(积性)函数

  • 费马小定理、欧拉定理、扩展欧拉定理

  • 逆元及其线性求法

  • 二元一次不定方程、线性同余方程、线性同余方程组

  • 卢卡斯定理


数论基础

整除?应该 0 个人不会吧!

约数、倍数、质数、合数,不会的可以立刻退役了……

gcd 与 lcm

  • 随机抽个人默写一下辗转相除法的代码,顺便说一下 gcd 与 lcm 的数量关系。

同余

  • 可加性,可减性,可乘性,可乘方性(思考:为什么没有可除性?)。

分解质因数

  • 抽个人说一下时间复杂度。

例题

No.1

给定正整数 \(L,R(1 \le L \le R \le 2 \times 10^9 ,\ R-L \le 10^6)\),求 \([L,R]\) 内质数个数。

No.2

记正整数 \(x\) 的约数个数为 \(g(x)\),一个数是好的当且仅当 \( \forall i \in [1,x-1] ,\ g(x)>g(i)\)。给定 \(n(n \le 2 \times 10^9)\),求最大的 \(\le n\) 的好数。(高效进阶贴贴)


题解

No.1

线性筛没有前途,寄。合数 \(x\) 总是存在 \(\le \sqrt{x}\) 的因子,所以可以先把 \(\sqrt{R}\) 范围内的质数筛出来,再用质数标记 \([L,R]\) 范围内的合数,完结撒花。

No.2

对好数质因数分解成如下形式 \({p_1}^{k_1} \times {p_2}^{k_2} \dots \times {p_m}^{k_m}\),一定有 \(k\) 单调不升,否则你总能找到约数个数与之相同的但数值更小的数,与好数定义矛盾。

\([1,2 \times 10^9]\) 范围内,一个数最多分解出 \(11\) 个质因子,所以可以直接开搜了,也可以打表,条条大路通罗马。


数论分块

先来到例题练练手——

给定 \(n(1 \le n \le 10^6)\),求 \(\sum_{i=1}^{n} \lfloor \frac{n}{i} \rfloor\) 的值。

哦,基础循环语句练习题。

简单修改一下数据范围,现在要求 \(1 \le n \le 10^{12}\),咋做?

需要用到大名鼎鼎的数论分块

如果你手模能力很强,你就会发现把 \(\big\lfloor \frac{n}{i} \big\rfloor\) 丢到一个序列上,取值相同的部分在序列上会形成连续段的形式。

然后你又发现这些取值构成的集合,集合大小不会超过 \(2 \sqrt{n}\)


数论分块

出现了神秘的根号状物,所以做上面这个题就需要去往根号上面靠一靠。

\(l\) 为分块左边界,记这个块的值为 \(k\),则 \(k=\big\lfloor \frac{n}{l} \big\rfloor\)。显然这个块的有边界 \(r\) 是最大的 \(\le \frac{n}{k}\) 的位置,将 \(k\) 代入后也就是 \(\Big\lfloor \frac{n}{\lfloor \frac{n}{l} \rfloor} \Big\rfloor\)

核心代码:

inline ll solve(ll n){
    ll l=1,r=0,res=0;
    while(l<=n){
        r=n/(n/l);
        res+=n/l*(r-l+1);
        l=r+1;
    }
    return res;
}

若干思考题

No.1

给定 \(n(n \le {10}^{12})\),求满足 \(ab,ac,bc\)\(\le n\) 的有序三元组 \((a,b,c)\) 个数。

No.2

\(g(x)\) 表示 \(x\) 的约数个数,给定 \(L,R(1 \le L \le R \le 10^9)\),求 \(\sum_{i=L}^{R} g(i)\)

No.3

计算:

\[\sum_{i=1}^{n} \sum_{j=1}^{m} (n \bmod i ) \times (m \bmod j) \]

其中正整数 \(n,m\) 满足 \(1 \le n,m \le 10^9\)


题解

No.1

\(B=\big\lfloor \sqrt{n} \big\rfloor\)

  • \(a,b,c \le B\),则对答案的贡献是 \(B^3\)

  • \(a > B\),由题意,\(b,c \le B\),所以枚举 \(a\),贡献形如:

\[\Bigg( \sum_{i=B+1}^{n} \Big\lfloor \frac{n}{i} \Big\rfloor \Bigg) ^2 \]

变成数论分块板板题咯!

有序三元组,答案还得 \(\times 3\),因为 \(b,c\) 都有可能成为 \(>B\) 的那个“幸运儿”。


题解

No.2

首先把区间问题转化为前缀问题,最后差分一下

容易发现,正整数 \(i\)\([1,n]\) 范围内作为约数出现的次数为 \(\big\lfloor \frac{n}{i} \big\rfloor\)。那么,对于约数 \(i\),约数和贡献形如 \(i \times \big\lfloor \frac{n}{i} \big\rfloor\)

那么一个前缀 \([1,n]\) 的答案应当是如下形式:

\[\sum_{i=1}^{n} i \Big\lfloor \frac{n}{i} \Big\rfloor \]

数论分块告诉我们,在同一个块内,\(\big\lfloor \frac{n}{i} \big\rfloor\) 的值总是相同的。因此,在同一个块内,只需要考虑 \(\sum i\) 的值即可,显然可以 \(O(1)\) 计算。


题解

No.3

先推式子……记原式为 \(ans\)

\[\begin{aligned} ans &= \Big( \sum_{i=1}^{n} (n \bmod i ) \Big) \times \Big( \sum_{j=1}^{m} (m \bmod j) \Big) \\ &= \Big( \sum_{i=1}^{n} \big( n - i \Big\lfloor \frac{n}{i} \Big\rfloor \big) \Big) \times \Big( \sum_{j=1}^{m} \big( m - j \Big\lfloor \frac{m}{j} \Big\rfloor \big) \Big) \\ &= \Big( n^2 - \sum_{i=1}^{n} i \Big\lfloor \frac{n}{i} \Big\rfloor \Big) \times \Big( m^2 - \sum_{j=1}^{m} j \Big\lfloor \frac{m}{j} \Big\rfloor \Big) \end{aligned} \]

推到这里还不会做就回炉重造叭!


筛法与欧拉(积性)函数

埃氏筛

  • 怎么写?

  • 时间复杂度?

线性筛,又称欧拉筛

  • 比埃氏筛快在哪里?

欧拉函数

  • 一些重要结论?

埃氏筛

从小到大枚举,判定质数的条件是当枚举到这个数的时候,它没有被标记为合数。

什么时候会被标记为合数?当出现一个质数 \(p\) 的时候,标记所有的 \(i \times p\) 为合数。

时间复杂度 \(O(n \log \log n)\)

bool isprime[N];int prime[N],tot;
inline void eratos(){
    memset(isprime,true,sizeof(isprime));
    isprime[1]=false;
    for(int i=2;i<=n;i++){
        if(!isprime[i])continue;
        prime[++tot]=i;
        for(int j=i*i;j<=n;j+=i)isprime[j]=false;
    }
    return;
}

线性筛

当合数被筛掉的时候,我们希望他只被筛一次,所以……

bool isprime[N];int prime[N],tot;
inline void euler(){
    memset(isprime,true,sizeof(isprime));
    isprime[1]=false;
    for(int i=2;i<=n;i++){
        if(isprime[i])prime[++tot]=i;
        for(int j=1;j<=tot&&i*prime[j]<=n;j++){
            isprime[i*prime[j]]=false;
            if(i%prime[j]==0)break;// 保证复杂度的关键语句捏!
        }
    }
    return;
}

时间复杂度 \(O(n)\)


欧拉函数

一起来康康欧拉函数的相关性质:

  1. \(\varphi(x)\) 是积性函数(不是完全积性函数)。

  2. 对于任意的质数 \(p\)\(\varphi(p)=p-1\)

  3. 对于任意的质数 \(p\)\(\varphi(p^k)=p^k-p^{k-1}\)

  4. \(\sum\limits_{d|n} \varphi(d) = n\)


欧拉函数

啥子是积性函数?啥子是完全积性函数?

  • 积性函数:若函数 \(f(n)\) 满足 \(f(1)=1\),且 \(f(xy)=f(x)f(y)\) 对任意互质的 \(x,y \in \mathbf{N}^*\) 都成立,则 \(f(n)\) 为积性函数。

  • 完全积性函数:若函数 \(f(n)\) 满足 \(f(1)=1\),且 \(f(xy)=f(x)f(y)\) 对任意的 \(x,y \in \mathbf{N}^*\) 都成立,则 \(f(n)\) 为积性函数。


欧拉函数

对上面几个性质弄一些简单的证明(告别 OI,走向数竞)。

  • 对于任意的质数 \(p\)\(\varphi(p)=p-1\)

证明:显然只有 \(p\) 本身与 \(p\) 不互质,所以是 \(p-1\)

  • 对于任意的质数 \(p\)\(\varphi(p^k)=p^k-p^{k-1}\)

证明:注意到与 \(p^k\) 不互质的数只有 \(p,2p,3p,\dots,p^{k-1}p\),共计 \(p^{k-1}\) 个,所以与 \(p^k\) 互质的有 \(p^k-p^{k-1}\) 个。

推广:对于任意的 \(x\),根据唯一分解定理,即 \(x=\prod p_i^{k_i}\)\(\varphi(x)=x \prod (1-\frac{1}{p_i})\)

剩下俩不证了,积性函数那个可以容斥原理结合上面这个推广简单证明;带求和号的那个,重点在于证明那个式子也是积性函数。感兴趣的可以自己尝试一下。


欧拉函数

单次 \(O(n)\) 或者 \(O(\sqrt{n})\)\(\varphi\) 的朴素暴力做法还是太笨拙了,欠优化。

筛法它本来就不是只用于筛质数的,筛法可以快速解决一些积性函数的求值问题。

bool isprime[N];int prime[N],tot,phi[N];
inline void euler(){
    phi[1]=1;
    memset(isprime,true,sizeof(isprime));
    isprime[1]=false;
    for(int i=2;i<=n;i++){
        if(isprime[i])prime[++tot]=i,phi[i]=i-1;
        for(int j=1;j<=tot&&i*prime[j]<=n;j++){
            isprime[i*prime[j]]=false;
            if(i%prime[j]==0){phi[i*prime[j]]=phi[i]*prime[j];break;}
            phi[i*prime[j]]=phi[i]*phi[prime[j]];
        }
    }
    return;
}

欧拉函数

初始化 phi[1]=1 不多赘述。

代码里有三个部分是计算 phi 的,一三都比较显然,就是前面的重要结论。

第二个部分需要简单推一下(需要用到前面的“推广”)……

\[\begin{aligned} \varphi(i \times p) &= (i \times p) \prod(1-\frac{1}{p_i}) \\ &= (i \times \prod(1-\frac{1}{p_i})) \times p \\ &= \varphi(i) \times p \end{aligned} \]

因为 i%prime[j]==0,所以后面的 \(\prod\) 不会出现少乘一项的情况,美滋滋。


例题

No.1

给定 \(n(1 \le n \le 10^7)\),求 \(1 \le x,y \le n\)\(\gcd(x,y)\) 为质数的 \((x,y)\) 的数目。

No.2

给定一个正整数 \(n\),每次操作形如 \(n \gets \varphi(n)\),问至少多少次操作之后 \(n=1\)。注意:\(n\) 以唯一分解的形式给出,即:

\[n = \prod_{i=1}^{m} {p_i}^{q_i} \]

数据范围:\(1 \le m \le 2000 ,\ 1 \le p_i \le 10^5 ,\ 1 \le q_i \le 10^9\)


题解

No.1

抽象成式子,大概长下面这个样子:

\[\sum_{i=1}^{n} \sum_{j=1}^{n} [\gcd(i,j) \ \text{is prime}] \]

典中典之枚举 \(\gcd\),上式化为:

\[\sum_{d \in [1,n],d \ \text{is prime}}\sum_{i=1}^{n} \sum_{j=1}^{n} [\gcd(i,j) = d] \]


对于 \(i,j\) 的两层枚举来说,\(d\) 是一个定值,所以直接转化为 \(i,j\) 互质的情况,即:

\[\sum_{d \in [1,n],d \ \text{is prime}}\sum_{i=1}^{\lfloor \frac{n}{d} \rfloor} \sum_{j=1}^{\lfloor \frac{n}{d} \rfloor} [\gcd(i,j) = 1] \]

你发现后面这坨是有序对,直接改变 \(j\) 的枚举上界转成无序对最后在 \(\times 2\),也就是:

\[\sum_{d \in [1,n],d \ \text{is prime}}\sum_{i=1}^{\lfloor \frac{n}{d} \rfloor} \Big( 2\sum_{j=1}^{i} [\gcd(i,j) = 1] \Big) -1 \]


对于这个式子,把 \(2\) 提出去,然后就是 \(\varphi(i)\) 咯!式子如下:

\[\sum_{d \in [1,n],d \ \text{is prime}} \Bigg(2\sum_{i=1}^{\lfloor \frac{n}{d} \rfloor} \varphi(i) -1 \Bigg) \]

线性筛出来 \(\varphi\) 值,再做一个前缀和预处理,剩下的交给基础循环语句即可。

时间复杂度 \(O(n)\)


题解

No.2

先来看看一次操作所带来的影响是什么。

\[\varphi(n) = n \times \prod_{i=1}^{m} (1-\frac{1}{p_i}) \]

这式子不可看,把一些邪恶的分母干掉,有:

\[\varphi(n) = \prod_{i=1}^{m} (p_i-1) \times {p_i}^{q_i-1} \]

你注意到这个式子告诉你,一次操作相当于对于所有的质因子,每种挑选一个 \(-1\) 之后再和原来的部分累乘合并。


还有一个观察,对于方程 \(\varphi(x)=1\),方程只有两个解 \(x_1=1,x_2=2\)

然而 \(\times 1\) 是没有任何影响的,所以操作次数等价于整套流程中质因子 \(2\) 的出现次数。

那么,除了一开始分解出来的 \(2\) 以外,还有什么东西会生产 \(2\)

自然就是 \(p_i-1\) 的部分,它们会在下一次操作时参与分解。

因此,考虑 DP。记 \(f_i\) 表示自然数 \(i\) 能在整套分解流程中生产的 \(2\) 的数量。

转移有两种,简单分讨一下:

  • \(i\) 是质数,显然 \(f_i=f_{i-1}\)

  • \(i\) 不是质数,令 \(xy=i\),则 \(f_i = f_x + f_y\)

这是一个经典的加性函数,可以在线性筛的时候求出来。


其实到这里差不多了,由于上面 \(p_i\) 上面还挂着一个 \(q_i\),所以答案是 \(\sum{f_{p_i} \times q_i}\)

然而,这么写的话 WA 将是你的归宿。

corner case 就是 \(n\) 不包含质因子 \(2\),也就是说第一轮不会消耗 \(2\),需要多操作一轮。

核心代码:

inline void euler(int n){
    f[1]=1;
    for(int i=2;i<=n;i++){
        if(!isprime[i])prime[++tot]=i,f[i]=f[i-1];
        for(int j=1;j<=tot&&i*prime[j]<=n;j++){
            isprime[i*prime[j]]=true;f[i*prime[j]]=f[i]+f[prime[j]];
            if(i%prime[j]==0)break;
        }
    }
    return;
}

费马小定理、欧拉定理、扩展欧拉定理

费马小定理:对于质数 \(p\) 和正整数 \(a\)\(p \nmid a\),有 \(a^{p-1} \equiv 1 \pmod{p}\)

欧拉定理:对于正整数 \(a,m\)\(\gcd(a,m)=1\),有 \(a^{\varphi(m)} \equiv 1 \pmod{m}\)

扩展欧拉定理:

对于任意正整数 \(a,m\) 和自然数 \(k\) ,有:

\[a^k \equiv \begin{cases} a^{k \bmod \varphi(m)} &\gcd(a,m) = 1 \\ a^k &\gcd(a,m)\neq 1, k \le \varphi(m) \\ a^{(k \bmod \varphi(m)) + \varphi(m)} &\gcd(a,m)\neq 1, k > \varphi(m) \end{cases} \pmod m \]

根据扩展欧拉定理,我们可以解决指数较大的模意义下计算。具体地,按上式第三种情况反复缩小规模,直到满足第二种情况,快速幂计算。这个行为又称欧拉降幂。


证明

这一部分与 OI 相去甚远,感兴趣的可以自行阅读。


欧拉定理的证明

我们对模数 \(m\) 取出 \([1,m-1]\) 范围内所有与它互质的数,记作 \(b_1,b_2,\dots,b_{\varphi(m)}\)

\[\begin{aligned} &\because \gcd(a,m)=1 ,\ \gcd(b_i,m)=1 \\ &\therefore \gcd (ab_i,m)=1 \\ &\therefore \gcd (ab_i \bmod m,m)=1 \end{aligned} \]

推论:定义 \(A_i = ab_i \bmod m\),序列 \(A\) 中所有元素均与 \(m\) 互质且两两不同。

推论的证明:考虑反证法。
假设存在 \(ab_i \equiv ab_j \pmod{m}\),则一定有 \(a(b_i-b_j) \equiv 0 \pmod{m}\)
因为 \(\gcd(a,m)=1\),故 \(b_i-b_j \equiv 0 \pmod{m}\),即 \(b_i \equiv b_j \pmod{m}\)
这与当初的 \(b\) 序列的定义是矛盾的,故假设不成立,结论得证。

所以 \(A\) 中的每个元素一定与 \(b\) 中的一个数同余,且一一对应。


根据以上推理,可以写出如下式子:

\[a^{\varphi (m)}\prod_{i=1}^{\varphi (m)}b_i \equiv \prod_{i=1}^{\varphi (m)}ab_i \equiv \prod_{i=1}^{\varphi (m)}b_i \pmod{m} \]

取一三两部分,移项得:

\[(a^{\varphi (m)}-1)\prod_{i=1}^{\varphi (m)}b_i \equiv 0 \pmod{m} \]

聪明的你一定发现了,因为 \(\gcd(b_i,m)=1\),所以有:

\[a^{\varphi (m)}-1 \equiv 0 \pmod{m} \]

最后一步再移一下项,宣告撒花。

\[a^{\varphi (m)} \equiv 1 \pmod{m} \]


费马小定理的证明

方才已经证明了欧拉定理,所以欧拉定理可以直接食用。

将质数 \(p\) 代入欧拉定理中,有:

\[a^{\varphi(p)} \equiv 1 \pmod{p} \]

众所周知 \(\varphi(p)=p-1\),所以嘛——

\[a^{p-1} \equiv 1 \pmod{p} \]

\(Q.E.D.\)

花絮:现在知道指数上这个稀奇古怪的 \(p-1\) 是怎么一回事了吧……


扩展欧拉定理的证明

\(\texttt{case 1}\)

考虑把指数 \(k\) 拆分为 \(b \times \varphi(m) + k \bmod \varphi(m)\)

具体地,按下面推式子:

\[\begin{aligned} a^k = a^{b \times \varphi(m) + k \bmod \varphi(m)} =\big(a^{\varphi(m)}\big)^b \times a^{k \bmod \varphi(m)} \end{aligned} \]

根据欧拉定理 \(a^{\varphi(m)} \equiv 1 \pmod{m}\),有:

\[a^k \equiv a^{k \bmod \varphi(m)} \pmod{m} \]

结论得证了捏,撒花!

\(\texttt{case 2}\)

正确性显然,无需证明。


\(\texttt{case 3}\)

原命题充要转化:对于 \(a\) 中质因子 \(p\),满足 \(p^k \equiv p^{(k \bmod \varphi(m)) + \varphi(m)} \pmod{m}\)

充要转化的正确性显然,考虑 \(a\) 的唯一分解,结合余数的可乘性和可乘方性可以简单证明,这里不多赘述。

\(p,m\) 互质,转化为 \(\texttt{case 1}\);否则 \(\gcd(p,m) \neq 1\),由于 \(p\) 是质数,则 \(p \mid m\)

经典操作之令 \(m=s \times p^r\),其中 \(\gcd(s,p)=1\),显然有 \(\varphi(m) = \varphi(s) \times \varphi(p^r)\)

\(\varphi(m) = \varphi(s) \times \varphi(p^r)\) 代入,结合欧拉定理 \(p^{\varphi(s)} \equiv 1 \pmod{s}\),有:

\[p^{\varphi(m)} = (p^{\varphi(s)})^{\varphi(p^r)} \equiv 1 \pmod{s} \]

两边同时乘 \(p^r\) 得:

\[p^{r+\varphi(m)} \equiv p^r \pmod{m} \]


显然有 \(k \ge \varphi(m) \ge r\)(不是,这显然吗?)

根据上页最后一个式子,有如下推理:

\[\begin{aligned} p^k &= p^{k-r} \cdot p^r \equiv p^{k-r} \cdot p^{r+\varphi(m)} = p^{k+\varphi(m)} \pmod{m} \end{aligned} \]

然后搞点高一数学,设定义在 \([\varphi(m),+\infty)\) 的函数 \(f(x)\) 满足 \(f(x)=p^x \bmod m\)

根据上式,当 \(x \ge \varphi(m)\) 时,有 \(f(x)=f(x+\varphi(m))\)。进一步地,当 \(x \ge 2 \varphi(m)\) 时,有 \(f(x)=f(x-\varphi(m))\)

容易发现,\(f(x)=f((x \bmod \varphi(m)) + \varphi(m))\),代入 \(x=k\),有

\[p^k \equiv p^{(k \bmod \varphi(m)) + \varphi(m)} \pmod m \]

\(Q.E.D.\)


例题

费马小定理在 oi 中最经典的应用还是逆元,所以咱们弄一点欧拉定理的好东西。

No.1

无穷序列 \(a\) 满足 \(a_0=1,a_n=2^{a_{n-1}}\)。给定一个正整数 \(m(1 \le m \le 10^7)\),可以证明 \(b_n​=a_n \bmod m\) 在某一项后都是同一个值,求这个值。

No.2

给定一个序列长度为 \(n(1 \le n \le 10^5)\) 的序列 \(a\) 和正整数 \(m(1 \le m \le 10^9)\)\(q(1 \le q \le 10^5)\) 次查询区间 \([l,r]\),求 \({a_l}^{{a_{l+1}}^{{\cdots}^{a_r}}} \bmod m\) 的值。


题解

No.1

指数一层一层递归掉,欧拉降幂。降幂过程中需要多次求 \(\varphi\),线性筛预处理即可。

No.2

欧拉降幂显然,但时间复杂度 \(O(nq\log V)\),因为一次降幂只能干掉 \(O(1)\) 个数。

注意到有效的降幂层数不多,每次降幂相当于给模数不断复合 \(\varphi\),又有 \(\varphi(1)=1\)

根据欧拉函数的性质,可以断言最多降幂 \(O(\log q)\) 次。

  • \(x>2\) 时,\(\varphi(x)\) 是偶数;
  • \(x\) 是偶数时,\(\varphi(x) \le \frac{x}{2}\)

上述性质显然,断言成立,时间复杂度 \(O(q \log n \log V)\)


逆元及其线性求法

单个逆元求法

  • 质数?快速幂(费马小定理)

  • 任意一数?逆元存在就扩展欧几里得,否则就不存在呗。

多个逆元求法

  • 质数?抽个人报一下式子。

  • 任意多数?前缀积,然后逆元性质了解一下。

抓一个幸运儿,依次报一下上面每种做法的时间复杂度。


例题

No.1

给出长度 \(n\) 的序列 \(a\)\(q\) 次询问 \(\prod_{i=l}^{r} \text{​lcm} (a_i​,x)\) 的值(所有变量均在 \([1,10^5]\) 内)。

No.2

luogu P2054


题解

(题解被云落给咕掉了)

第一个题需要推式子,不想码 latex。

第二个题是拍脑袋题,不知道各位有没有拍脑袋拍出来。

bg right


题解

开玩笑的,云落还是会写题解的,就是第一个题 latex 有点扭曲,给诸位先打个预防针。

No.1

查询 \(\text{lcm}\) 可以转化为 \(\gcd\),需要维护一个 \(x\) 的幂和区间积,快速幂和前缀积搞定。

现在问题转化为,在合理的时间复杂度内,求下列式子的值。

\[\prod_{i=l}^{r} \gcd(a_i,x) \]

推式子肯定是要推的,诸位可以简单思考一下,有哪些推式子的 trick。

唉,质因数唯一分解在数论中的地位还是太举足轻重了。


考虑分别对 \(a_i,x\) 质因数分解,记原式结果为 \(A\),有:

\[\begin{aligned} A &= \prod_{i=l}^{r} \prod_{j=1}^{k} {p_j}^{\min (q_i[j],q_x[j])} \\ &= \prod_{i=1}^{k} {p_i}^{\sum_{j=l}^{r} \min(q_j[i],q_x[i])} \\ &= \prod_{i=1}^{k} {p_i}^{\sum_{j=l}^{r}\sum_{t=1}^{q_x[i]} [t \le q_j[i]]} \\ &= \prod_{i=1}^{k} {p_i}^{\sum_{j=l}^{r}\sum_{t=1}^{q_x[i]} [{p_i}^t \mid {p_i}^{q_j[i]}]} \\ &= \prod_{i=1}^{k} {p_i}^{\sum_{j=l}^{r}\sum_{t=1}^{q_x[i]} [{p_i}^t \mid a_j]} \\ \end{aligned} \]


这个式子的实际含义等价于对于每个质因子,求区间内可以分解出该质因子的数目。

不需要任何神秘的数据结构,只需要一个小小的 vector 加一个小小的二分即解决。

具体地,对于每个质因子 \(p\)\(t\) 次幂 \(p^t\),我们用 vector 维护所有以 \(p^t\) 为约数的 \(a_i\) 的下标 \(i\)。查询的时候直接在 vector 上二分 \(l,r\) 的位置。

代码上还有很多细节,云落后面会结合代码来说。

时间复杂度 \(O(q \log n \log V)\)


signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n>>q;
    for(int i=1;i<=n;i++)cin>>a[i];
    euler(N-5);init();
    while(q--){
        int l,r,x;cin>>l>>r>>x;
        int ans=mul[r]*qpow(mul[l-1],MOD-2)%MOD*qpow(x,r-l+1)%MOD;
        while(x>1){
            int t=d[x],p=1,sum=0;
            while(x%t==0){
                x/=t,p*=t;
                auto L=lwbd(vec[p].begin(),vec[p].end(),l),R=upbd(vec[p].begin(),vec[p].end(),r);
                sum+=(R-L);
            }
            ans=ans*(qpow(qpow(t,sum),MOD-2)%MOD)%MOD;
        }
        cout<<ans<<'\n';
    }
    return 0;
}

inline void euler(int n){
    memset(isprime,true,sizeof(isprime));
    isprime[1]=false;
    for(int i=2;i<=n;i++){
        if(isprime[i])prime[++tot]=i,d[i]=i;
        for(int j=1;j<=tot&&i*prime[j]<=n;j++){
            isprime[i*prime[j]]=false;d[i*prime[j]]=prime[j];
            if(i%prime[j]==0)break;
        }
    }
    return;
}
inline void init(){
    mul[0]=1;
    for(int i=1;i<=n;i++)mul[i]=mul[i-1]*a[i]%MOD;
    for(int i=1;i<=n;i++){
        int x=a[i];
        while(x>1){
            int t=d[x],p=1;
            while(x%t==0)x/=t,p*=t,vec[p].pb(i);
        }
    }
    return;
}

题解

No.2

开始手模,假设初始牌序是 \(\{1,2,3,4,5,6\}\),接下来展示若干轮洗牌后的牌序。

  • 第一轮洗牌后:\(\{4,1,5,2,6,3\}\)
  • 第二轮洗牌后:\(\{2,4,6,1,3,5\}\)
  • 第三轮洗牌后:\(\{1,2,3,4,5,6\}\)

你发现:假设洗牌前的位置为 \(x\),则一轮洗牌后的位置为 \(2x \bmod (n+1)\)

容易想到,答案就是同余方程 \(2^m \times x \equiv l \pmod{n+1}\) 的解,计算 \(2^m\) 在模 \(n\) 意义下的乘法逆元就行了嘛!


二元一次不定方程、线性同余方程、线性同余方程组

在上一道题目的渗透下,我们已经初步触摸到和数论有关方程的门槛了。

开始方程之旅之前,必然要知悉裴蜀定理

裴蜀定理:对于正整数 \(a,b\),对于任意的 \(x,y\) 都有 \(\gcd(a,b) \mid ax+by\)。特别地,一定存在一组 \(x,y\),使得 \(\gcd(a,b)=ax+by\) 成立。
重要推论:正整数 \(a,b\) 互质的充要条件是存在整数 \(x,y\) 使得 \(ax+by=1\)

好的,你已经学会了最重要的东西,接下来请你分别求出下列不定方程中 \(x,y\) 的一组整数解(或报告无解),其中 \(a,b,c\) 都是给定的正整数。

\[ax+by=c \]

这个时候 exgcd 闪亮登场,exgcd 可以解决 \(ax+by=\gcd(x,y)\) 的一组整数解。


二元一次不定方程、线性同余方程、线性同余方程组

象征性意义的贴一下 exgcd 的模板……

inline int exgcd(int a,int b,int &x,int &y){
    if(b==0){x=1,y=0;return a;}
    int d=exgcd(b,a%b,x,y);
    int tmp=x;
    x=y,y=tmp-a/b*y;
    return d;
}
  • \(c\) 不是 \(\gcd(a,b)\) 的倍数就直接无解;
  • 用 exgcd 解出一组 \(x,y\),然后分别乘上 \(\frac{c}{\gcd(a,b)}\) 得到原方程的一组特解;
  • 于是乎就没有然后了(要是求最小正整数解之类的东西,可以接着往下推,找到通解形式即可)。

二元一次不定方程、线性同余方程、线性同余方程组

那么,我们跑步前进,来看线性同余方程,其形式如下:

\[ax \equiv b \pmod{m} \]

转化一下,这个线性同余方程等价于不定方程——

\[ax+ny=b \]

好的,回到原来的问题上去了,直接 exgcd 即可。

当然从逆元的角度来理解也是可以的,只不过未保证 \(m\) 是质数,还得落到 exgcd 上。


例题

高效进阶已经急不可耐了,放两道高效进阶进来。

No.1

给定 \(n\) 元环,环上有两动点 \(A,B\)。动点 \(A,B\) 初始分别在 \(x,y\) 上,并即将顺时针移动。移动定义为在原地消失,在远方刷新。动点 \(A,B\) 的单次移动距离分别是 \(d1,d2\)。问两动点同时在某个位置上刷新的最少时间(或报告永远无法同时刷新在同一位置)。

No.2

luogu P2421

(这俩题不写题解了,都比较板子)


二元一次不定方程、线性同余方程、线性同余方程组

问:有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?
答:三人同行七十希,五树梅花廿一支,七子团圆正半月,除百零五便得知。

古老而神秘的华夏,孕育出了解决线性同余方程组的方法——中国剩余定理。

放一个线性同余方程组的标准形式。

\[\begin{cases} x \equiv a_1 \pmod {m_1} \\ x \equiv a_2 \pmod {m_2} \\ \ \ \ \ \vdots \\ x \equiv a_k \pmod {m_k} \\ \end{cases} \]

上面的「物不知数」问题就是一元线性同余方程组的一个实例。


二元一次不定方程、线性同余方程、线性同余方程组

先讲 CRT,要求模数上两两互质。

  1. 计算所有模数的积 \(M\)

  2. 对于第 \(i\) 个同余方程,分三步;

  • 计算 \(b_i=\frac{M}{m_i}\)
  • 计算 \(b_i\) 在模 \(m_i\) 意义下的逆元 \({b_i}^{-1}\)
  • 计算 \(c_i=b_i{b_i}^{-1}\)
  1. 解得 \(x \equiv \sum_{i=1}^{k}a_ic_i \pmod{M}\)

这没什么可解释的,证明起来比较复杂,直接背就行了……

建议打个板子,当 exgcd 的练手题。


二元一次不定方程、线性同余方程、线性同余方程组

重点是 excrt,没有什么更多的条件限制,而且思路也更符合人类惯性思维一些。

excrt 的核心思想就是把两个同余方程捏成一个同余方程,给一些数学上的推导。

\[\begin{cases} x \equiv a \pmod {A} \\ x \equiv b \pmod {B} \end{cases} \]

同余方程不好看,还是先归约到不定方程的形式,如下:

\[\begin{cases} x=a+Am \\ x=b-Bn \end{cases} \]

然后干掉未知数 \(x\),获得关于 \(m,n\) 的不定方程,即:

\[Am+Bn=b-a \]


二元一次不定方程、线性同余方程、线性同余方程组

上页最后一个式子显然是一个不定方程的基本形式,exgcd 可以简单获取这个不定方程的一组特解 \((m',n')\)(或报告无解)。把 \(m'\)(或 \(n'\))代回到最初的不定方程组中,可以获取一个 \(x\) 的特解 \(x=x'\)

现在问题在于,如何通过 \(x=x'\) 这一特解反向推出合并后的同余方程?

注意到两个同余方程的模数分别是 \(A,B\),所以可以发现,若 \(x=x'\) 是原方程组的一个特解,那么 \(x=x'+\text{lcm}(A,B)\) 也一定是一个合法的特解。

进一步地,\(x=x'+k \times \text{lcm}(A,B)\) 一定是 \(x\) 的通解表现形式。

这样我们只需要把上面这个通解写成同余的形式即可,形如:

\[x \equiv x' \pmod{\text{lcm}(A,B)} \]

综上所述,我们完成了两个同余方程的合并,也就能解线性同余方程组了。


二元一次不定方程、线性同余方程、线性同余方程组

代码展示(模板题需要开 __int128 防止乘法溢出)

inline ll exgcd(ll a,ll b,i2 &x,i2 &y){
    if(b==0){x=1,y=0;return a;}
    ll d=exgcd(b,a%b,x,y);i2 tmp=x;
    x=y,y=tmp-a/b*y;
    return d;
}
signed main(){
    cin>>n>>A>>a;
    for(int i=2;i<=n;i++){
        ll B,b;cin>>B>>b;
        ll g=exgcd(A,B,x,y),lcm=A/g*B;
        i2 m=(i2)((b-a)/g*x),x0=A*m+a;
        a=(x0%lcm+lcm)%lcm,A=lcm;
    }
    cout<<a<<'\n';
    return 0;
}

例题

No.1

luogu P3868

(这个题找个人直接报做法吧……)

No.2

\(r \times c (1 \le r,c \le 10^6)\) 的二维平面上有一动点在 \((0,0)\) 处。一行命令形如长度为 \(n(1 \le n \le 10^6)\) 的字符串。字符只包含 UDLR,分别表示上下左右移动,每次动点只会按命令方向平移一格。若执行当前命令会越界,则将整个命令行中所有和当前命令相同的命令方向扭转 \(180 \degree\),命令行要重复执行 \(k(1 \le k \le 10^{12})\) 次,求所有命令执行结束之后,这个动点会经过多少次 \((0,0)\)


题解(No.2 sol)

命令扭转一眼不想什么好东西,而且数据范围奇大,不可模拟。

结论:如果不进行命令扭转,那么其新的横纵坐标 \((x',y')\) 和正常执行命令的横纵坐标 \((x,y)\) 一定满足:

\[\begin{cases} x' \equiv x \pmod{2r} \\ y' \equiv y \pmod{2c} \end{cases} \]

这启示我们可以直接忽略命令扭转的环节,在原命令上做就 OK 了。并且这个同余的限制保证了有效的活动范围并不是很大。

但是,答案怎么算捏?


题解(No.2 sol)

无法枚举路径依旧是个问题,然而命令行是反复出现的,这给予我们优化的空间。

先考虑单次命令行我们怎么做,显然是直接模拟,回到 \((0,0)\) 直接 ans++ 就做完了。

重复多次咋办?你发现可以维护单次命令行的偏移量(横 \(\Delta x\)\(\Delta y\)),然后知晓重复 \(t\) 次就可以求出总偏移量(横 \(t \cdot \Delta x\)\(t \cdot \Delta y\))。

对于出现在第 \(t+1\) 组命令行中的第 \(i\) 条命令,若它可以贡献给答案,则一定满足:

\[\begin{cases} t \cdot \Delta x + X_i &\equiv 0 \pmod{2r} \\ t \cdot \Delta y + Y_i &\equiv 0 \pmod{2c} \end{cases} \]

其中 \(X_i,Y_i\) 分别表示执行完前 \(i\) 条命令的横纵坐标偏移量。


题解(No.2 sol)

起猛了,看见方程组了。

再揉揉眼睛,啧,好像还是同余方程组。

那直接 excrt 把同余方程二合一,然后把新的同余方程的通解形式求出来之后,\(O(1)\) 计算 \(k\) 范围内的整数解的个数。


卢卡斯定理

跑步前进,先说定理。

对于素数 \(p\),有:

\[{n \choose k} \equiv {\lfloor \frac{n}{p} \rfloor \choose \lfloor \frac{k}{p} \rfloor} {{n\bmod p} \choose {k\bmod p}}\pmod {p} \]

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

你发现这是一个递归的形式,因为 \({\lfloor \frac{n}{p} \rfloor \choose \lfloor \frac{k}{p} \rfloor}\) 可以继续进行卢卡斯定理直到可以计算。

因此,我们只需要计算 \({{n\bmod p} \choose {k\bmod p}}\) 即可。

这对 \(p\) 的规模有一定的要求,显然不能够是 \(998244353\) 之类的大质数。

尽管有一定的局限性,但是依旧大大的好用!


例题

No.1

高效进阶稳定发挥。

计算 \(g^{\sum_{d \mid n} {n \choose d}} \bmod 999911659\)

数据范围:\(1 \le n,g \le 10^9\)

No.2

只能向右下方向跳跃的马。初始位置 \((0,0)\),目标位置 \((n,m)\)。有 \(k\) 个障碍物(不存在蹩马腿),求方案数对 \(10007\) 取模的值。


题解

No.1

终于等到你了古代猪文,数论全家桶说的就是你!

STEP 1 扩展欧拉定理

可以把这个东西先套一层扩展欧拉定理,为了方便表述记 \(A=\sum_{d \mid n} {n \choose d}\),用 \(ans\) 表示式子的值,则有:

\[ans = g^{A \bmod 999911658} \bmod 999911659 \]

STEP 2 费马小定理

显然下面这个次方的东西可以费马小定理快速做,问题在于求解 \(A \bmod 999911658\)


STEP 3 扩展中国剩余定理

就这么个模数,不是质数什么都是白搭,所以质因数分解之后写成同余方程组的形式。

温馨提示:\(999911658=2×3×4697×35617\)

具体地,记 \(x\) 表示 \(A \bmod 999911658\) 的结果,有:

\[\begin{cases} x \equiv A \pmod {2} \\ x \equiv A \pmod {3} \\ x \equiv A \pmod {4697} \\ x \equiv A \pmod {35617} \\ \end{cases} \]

excrt 可以直接合并同余方程组,现在问题就转化为:\(A\) 在单个同余方程中的取值

STEP 4 卢卡斯定理

组合数?还是取模?质数不超过 \(4 \times 10^4\)?卢卡斯定理直接安排上,完结撒花!


题解

No.2

\(f_{i,j}\) 表示跳跃到 \((i,j)\) 的方案数,显然 \(f_{i,j}\) 不为 \(0\) 的一个必要条件是 \(3 \mid i+j\)

设跳了 \(a\)\((+1,+2)\),跳了 \(b\)\((+2,+1)\)。若 \(a<0\) 或者 \(b<0\),则 \(f_{i,j}=0\)

考虑 DP,记 \(dp_i\) 表示到第 \(i\) 个障碍物前不碰到任何一个障碍物的方案数,答案是:

\[f_{n,m} - \sum_{i=1}^{k} dp_i f_{n-x_i,m-y_i} \]

转移方程也很好去写,形如:

\[dp_i = f_{x_i,y_i} - \sum_{x_j \le x_i,y_j \le y_i,j \neq i} dp_j f_{x_i-x_j,y_i-y_j} \]

问题转化为快速求 \(f_{i,j}\),如果有值,显然 \(f_{i,j}={a+b \choose b}\),模数较小,上卢卡斯定理。


转场

以上内容难度介于 Div2 和 Div1 之间,接下来简单 level-up 一下。

可能会涉及一些稍微困难的算法与知识点,诸位量力而行。


目录

  • 离散对数与 BSGS

  • 狄利克雷卷积与莫比乌斯反演

  • 杜教筛

  • 杂《》选吃


离散对数与 BSGS

你无需知道离散对数的具体定义,你只需知道你需要一个高效的算法解决下面的问题。

给定正整数 \(a,b,m\),保证 \(\gcd(a,m)=1\),解同余方程:

\[a^x \equiv b \pmod m \]

引入一个算法——BSGS,其可以在 \(O(\sqrt{m})\) 的时间复杂度内解决这个问题。

进一步地,如果 \(\gcd(a,m) \neq 1\),可以使用 exBSGS,时间复杂度也是 \(O(\sqrt{m})\)


离散对数与 BSGS

解决 \(a^x \equiv b \pmod{m}\) 的朴素做法是 \(O(m)\) 的。根据欧拉定理,\(x\) 所有的合法解中最小的那一个应当是 \(\varphi(m)\),所以是线性复杂度。

显然如果 \(m=998244353\),这种依据欧拉定理的暴力枚举就没有前途了。

注意到其实同余号右边的 \(b\) 没有起到任何作用。上面的朴素做法相当于 \(O(n)\) 预处理,然后 \(O(1)\) 判断。

像这种信息比对的东西,明显可以通过移项和哈希表的方式进行复杂度平衡。

比如求 \(a_x+a_y=C\) 的合法 \((x,y)\) 个数,除了暴力枚举 \(x,y\),还可以把 \(C-a_y\) 的所有值塞到哈希表里,然后用 \(a_x\) 去查询。


离散对数与 BSGS

这启发我们对 \(a^x \equiv b \pmod{m}\) 中的指数 \(x\) 动一些手术。

具体地,可以令 \(x=pc-q\)\(c\) 是由你决定的常数,于是有:

\[a^{pc} \equiv ba^q \pmod{m} \]

然后可以暴力枚举 \(q\),把所有 \(ba^q \bmod m\) 的取值丢到哈希表里面;再去暴力枚举 \(p\),把 \(a^{pc} \bmod m\) 的值放在哈希表里面查询。

显然以上算法一定是有正确性保证的。

当然,这里的 \(q\) 不应该大于 \(c\),而 \(p\) 的上界是 \(\frac{m}{c}\)

因此,\(O(c)\) 枚举 \(q\)\(O(\frac{m}{c})\) 枚举 \(p\),总时间复杂度为 \(O(c+\frac{m}{c})\)

根据均值不等式,容易发现 \(c\) 取到 \(\sqrt{m}\) 的时候 \(O(c+\frac{m}{c})\) 取到最小值,为 \(O(\sqrt{m})\)


离散对数与 BSGS

exBSGS 在 BSGS 基础上多了几步前置转化,可以用于解决 \(\gcd(a,m) \neq 1\) 的问题。

高端的问题往往只需要最简单的解决方式,既然他们不互质,就一直除到它互质即可。

\(d_1=\gcd(a,m)\),如果 \(b \bmod d_1 \neq 0\),则原方程一定无解,否则等价转化为:

\[\frac{a}{d_1} \cdot a^{x-1} \equiv \frac{b}{d_1} \pmod {{\frac{m}{d_1}}} \]

如果 \(a,\frac{m}{d_1}\) 依旧不互质,就取出 \(d_2=\gcd(a,\frac{m}{d1})\),重复执行上述操作。

跳出循环后,同余方程应该有如下形式:

\[\frac{a^k}{\prod d_i} \cdot a^{x-k} \equiv \frac{b}{\prod d_i} \pmod {{\frac{m}{\prod d_i}}} \]

简单做就好了,可以证明前面不断除以 \(d\) 的操作不能够成为时间复杂度瓶颈。


例题

给定正整数 \(k\) 和质数 \(m\),求最小正整数 \(n\),有 \(11 \cdots 1\)\(n\)\(1\)\(\equiv k \pmod {m}\)

数据范围:\(1 \le k < m \le 10^{12}\)

题解

容易发现,题目给出的同余式子可以转化为如下形式:

\[\frac{10^n-1}{9} \equiv k \pmod{m} \]

移项,简单 BSGS 即可。


留作习题?

APIO2025 T1……

其实是去学习了一下的,但感觉只是意会了,没有理好思路,就浅浅地留作习题叭!


狄利克雷卷积与莫比乌斯反演

可能会有若干蠕动的数学公式向我们大踏步的走来,请谨慎观看。

Q:什么是狄利克雷卷积?

A:一个定义在数论函数间的二元运算。

Q:什么是数论函数?

A:定义域为全体自然数的函数。


狄利克雷卷积与莫比乌斯反演

狄利克雷卷积的定义式为:

\[\Big( f*g \Big)(n):=\sum_{d \mid n}f(d)g(\frac{n}{d}) \]

如果你有点强迫症,希望后面这坨式子更好看一些,也可以写作:

\[\Big( f*g \Big)(n):=\sum_{xy=n}f(x)g(y) \]

举例:计算 \(\Big( f*g \Big)(6)\)


狄利克雷卷积与莫比乌斯反演

在引入一些比较重要的概念之前,我们来看一些比较重要的数论函数。

单位函数:\(\varepsilon(n)=[n=1]\)

幂函数:\(\operatorname{Id}_k(n)=n^k\)

特别地,

  • \(k=1\) 时,为恒等函数 \(\operatorname{Id}(n)=n\)

  • \(k=0\) 时,为常函数 \(\operatorname{I}(n)=1\)


狄利克雷卷积与莫比乌斯反演

除数函数:\(\sigma_k(n)=\sum_{d \mid n} d^k\)

特别地,

  • \(k=1\) 时,为约数和函数 \(\sigma(n)=n\)

  • \(k=0\) 时,为约数个数函数 \(\tau(n)=1\)

欧拉函数:\(\varphi(n)=n\prod\limits_{p \mid n,p \in \mathbb{P}}(1-\frac{1}{p})\)

本页包括上一页提及的所有函数都是积性函数。


狄利克雷卷积与莫比乌斯反演

狄利克雷卷积这一运算有很多特别优秀的性质,比如:

  1. \(f,g\) 是积性函数,则 \(f*g\) 也是积性函数;
  2. \(f*g=g*f\)
  3. \((f*g)*h=f*(g*h)\)
  4. \(f*(g+h)=f*g+f*h\)

篇幅有限,就不给出上述相关性质的证明了。感兴趣的话可以自己推,直接把定义式代入进去即可。


狄利克雷卷积与莫比乌斯反演

接下来将给出一些重要的数论函数的狄利克雷卷积结果。

  1. \(\operatorname{Id}_k*\operatorname{I}=\sigma(k)\)
  • 推广:\(\Big(f*\operatorname{I}\Big)(n)=\sum\limits_{d \mid n} f(d)\)
  1. \(\varphi*\operatorname{I}=\operatorname{Id}\)

  2. \(\operatorname{I}*\operatorname{I}=\tau\)

哎,这些东西会经常在莫反里面大放异彩。他们都有一个共同的性质——与 \(\operatorname{I}\) 卷积。


狄利克雷卷积与莫比乌斯反演

单位元相关……

你不需要知道单位元的具体定义。你只需要知道,如果一个函数 \(\omega\) 对于任意的数论函数 \(f\),在狄利克雷卷积运算中,满足 \(f*\omega=f\),则称 \(\omega\) 为狄利克雷卷积的单位元。

结论:狄利克雷卷积这一运算的单位元正是单位函数 \(\varepsilon(n)\)

这个结论正确性显然。

\[\Big( f*\varepsilon \Big)(n)=\sum_{d \mid n} \varepsilon(d) f(\frac{n}{d}) = f(n) \]

上式直观地阐释了结论的正确性。


狄利克雷卷积与莫比乌斯反演

狄利克雷逆相关……

定义:如果数论函数 \(f,f^{-1}\) 满足 \(f*f^{-1}=\varepsilon\),则称 \(f^{-1}\)\(f\) 的狄利克雷逆。

然后是一些关于狄利克雷逆的重要的性质或者结论。

  1. 一个数论函数 \(f(n)\) 存在狄利克雷逆的充要条件是 \(f(1) \neq 0\)
  2. \(f(n)\) 的狄利克雷逆如果存在,则一定有且仅有一个。
  3. 积性函数一定有狄利克雷逆,且其相应的狄利克雷逆也是积性函数。

狄利克雷卷积与莫比乌斯反演

长舒一口气,狄利克雷卷积的前置铺垫已经结束,接下来进入莫比乌斯反演。

先来聊莫比乌斯函数 \(\mu(n)\),给出两种定义:

定义一

\[\mu = \operatorname{I}^{-1} \]

定义二

\[\mu(n)= \begin{cases} 1&n=1 \\ 0&n\text{ 含有平方因子} \\ (-1)^k&k\text{ 为 }n\text{ 的本质不同质因子个数} \\ \end{cases} \]


狄利克雷卷积与莫比乌斯反演

根据定义一,容易发现如下结论

\[g=f*I \iff f=g*\mu \]

简单按狄利克雷卷积定义式展开,有:

\[g(n)=\sum_{d \mid n}f(d) \iff f(n)=\sum_{d \mid n} \mu(d)g(\frac{n}{d}) \]

由上式,我们称 \(g(n)\)\(f(n)\) 的莫比乌斯变换,\(f(n)\)\(g(n)\) 的莫比乌斯反演。


狄利克雷卷积与莫比乌斯反演

你发现莫比乌斯函数是一个积性函数,所以莫比乌斯函数值可以直接线性筛预处理。

可能在应用上各位还有些问题,这边建议结合下面的例题食用。

最常见的应用就是,结合前面狄利克雷卷积的相关公式,起到一个推式子的作用。


例题

\(T\) 组多测,给定正整数 \(a,b,d\),计算:

\[\sum_{x=1}^{a}\sum_{y=1}^{b}[\gcd(x,y)=d] \]

数据范围:\(1 \le T \le 5 \times 10^4 ,\ 1 \le d \le a,b \le 5\times 10^4\)

Hint or sol

显然是莫反推式子。


\[\begin{aligned} ans &= \sum_{i=1}^{\lfloor \frac{a}{d} \rfloor}\sum_{i=1}^{\lfloor \frac{b}{d} \rfloor} [\gcd(i,j)=1] \\ &= \sum_{i=1}^{\lfloor \frac{a}{d} \rfloor}\sum_{i=1}^{\lfloor \frac{b}{d} \rfloor} \sum_{x \mid \gcd(i,j)} \mu(x)\\ &= \sum_{x=1}^{\lfloor \frac{a}{d} \rfloor} \mu(x) \sum_{x \mid i}^{\lfloor \frac{a}{d} \rfloor}\sum_{x \mid j}^{\lfloor \frac{b}{d} \rfloor} 1\\ &= \sum_{x=1}^{\lfloor \frac{a}{d} \rfloor} \mu(x) \lfloor \frac{a}{xd} \rfloor \lfloor \frac{b}{xd} \rfloor \end{aligned} \]

数论分块即可。


留作习题?

建议诸位得空的时候,搜索一套莫反题单,全刷完就好了。


杜教筛

用于在优于线性时间复杂度求解数论函数的前缀和。

形式化地,对于数论函数 \(f(n)\),求 \(\sum_{i=1}^{n}f(i)\)

考虑构造一个数论函数 \(g\),根据前文狄利克雷卷积的知识,有:

\[\sum_{i=1}^{n}(f*g)(i) = \sum_{i=1}^{n} \sum_{d \mid i} g(d)f(\frac{i}{d}) = \sum_{i=1}^{n} \sum_{j=1}^{\lfloor \frac{n}{i} \rfloor}g(i)f(j)=\sum_{i=1}^{n}g(i)S \Big( \Big \lfloor \frac{n}{i} \Big \rfloor \Big) \]

记住这个式子,后面要考。


杜教筛

你发现你构造的这个东西,可以写出一个神秘的递推式,形如:

\[\begin{aligned} g(1)S(n) & = \sum_{i=1}^n g(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right) - \sum_{i=2}^n g(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right) \\ &= \sum_{i=1}^n (f * g)(i) - \sum_{i=2}^n g(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right) \end{aligned} \]

(云落曾经对着这个式子一直在犯唐……)

综上所述,只要构造出的 \(g\) 性质很优,支持快速计算 \(\sum_{i=1}^{n}(f*g)(i)\) 以及 \(g(i)\) 的前缀和,就可以在优于线性的时间复杂度内解决这个数论函数前缀和的问题。

具体地,前者直接算,后者数论分块。


例题

给定 \(n\),计算:

\[\sum_{i=1}^{n}\sum_{j=i+1}^{n} \gcd(i,j) \]

数据范围:\(1 \le n \le 10^{11}\)


题解

和前面莫反的例题很类似,枚举约数 \(d\),把 \([\gcd(i,j)=1]\) 的部分套个莫反,调整一下枚举上界……最后你会得到这样一个式子:

\[\sum_{d=1}^{n}d\sum_{i=1}^{\lfloor \frac{n}{d} \rfloor} \varphi(i) \]

\(S(n)=\sum_{i=1}^{n} \varphi(i)\),杜教筛板板题。

然后答案变成

\[\sum_{d=1}^{n}d \cdot S(\lfloor \frac{n}{d} \rfloor) \]

这回是数论分块板板题。


杂《》选吃

之所以设计这个部分,主要是云落个人认为,数论相关例题不应当照着算法标签写题。


Round 1

\(T\) 组多测。给定 \(n,m\),求 \([1,n!]\) 中与 \(m!\) 互质的数的数量。

答案对 \(p\) 取模,保证 \(p\) 是质数且 \(p>n\)

数据范围:\(1 \le T \le 10^4 ,\ 1 \le m \le n \le 10^7\)


Sol 1

形式化刻画答案,如下:

\[\sum_{i=1}^{n!}[\gcd(i,m!)=1]=\frac{n!}{m!} \cdot \varphi(m!) \]

根据经典结论 \(\gcd(x,y)=\gcd(x+y,y)\),如果存在一个 \(x \in [1,m!]\),使得 \(\gcd(x,m!)=1\),那么 \([km!+1,(k+1)m!]\) 范围内一定会唯一对应一个 \(x+km!\) 满足 \(\gcd(x+km!,m!)=1\)。这保证了上述式子的正确性。

然后把 \(m!\) 唯一分解了,写成 \(\prod {p_i}^{q_i}\) 的形式。

欧拉函数往里一带,\(m!\) 直接约掉,里面的 \(\prod\) 也就是四则运算的事,给分母求一求逆元就齐活了。


Round 2

给定一个序列 \(a\),定义其权值为:

\[\sum_{i=1}^{n} \gcd(a_1,a_2,\dots,a_i) \]

请你重排这个序列,最大化权值。

数据范围:\(1 \le n \le 10^5 ,\ 1 \le a_i \le 5 \times 10^6\)

温馨提示:时限 \(4s\),可以肆意挥霍。


Sol 2

\(f_i\) 表示目前前缀 \(\gcd\)\(i\),前缀 \(\gcd\) 和的最大值。

注意到重排后的序列上一定有一个性质,即对于任意一个前缀的 \(\gcd\),这个前缀以外的数一定都不是这个 \(\gcd\) 的倍数(调整法易证)。

为了方便方程刻画,记 \(cnt_i\) 表示含有因子 \(i\)\(a_i\) 的数量。

容易发现,对于一个 \(i\),你可以枚举它的所有倍数 \(j\) 作为转移来源,而对答案的贡献就一定是那些是 \(i\) 的倍数但不是 \(j\) 的倍数的数,即 \(cnt_i-cnt_j\)。因此,转移方程如下:

\[f_i = \max_{i \mid j}(f_j + (cnt_i-cnt_j) \times i) \]

时间复杂度 \(O(V \ln V)\),其中 \(V\) 表示值域。


Round 3

\(T\) 组多测。给定四个整数 \(a,b,c,d\),从区间 \([a,b]\)\([c,d]\) 中任选两个整数 \(x\)\(y\),求 \(\gcd(x,y)\) 的最大值是多少。

数据范围:\(1 \le T \le 10^3 ,\ 1 \le a,b,c,d \le 10^9\)


Sol 3

数论题特有的阴间数据范围,线性筛没什么前途,所以想到枚举这个神秘的 \(\gcd\)

你发现如果一个 \(\gcd\) 合法,那么在 \([a,b]\)\([c,d]\) 中一定有它的倍数。

判断一个区间 \([l,r]\) 是否存在 \(x\) 的倍数,经典套路之判断下列式子的合法性。

\[\lfloor \frac{r}{x} \rfloor - \lfloor \frac{l-1}{x} \rfloor \ge 1 \]

稍微整理一下,得到:

\[\lfloor \frac{r}{x} \rfloor > \lfloor \frac{l-1}{x} \rfloor \]


重要的进一步转化——

\[x \lfloor \frac{r}{x} \rfloor > l-1 \]

分别带入 \(a,b,c,d\),有:

\[\begin{cases} x\lfloor \frac{b}{x} \rfloor > a-1 \\ x\lfloor \frac{d}{x} \rfloor > c-1 \end{cases} \]

根据上面的式子,我们就没有必要线性复杂度枚举 \(x\) 了,套一个简单整除分块
即可,时间复杂度根号量级。


Round 4

\(T\) 组多测。给定 \(n,m\),求序列 \(a_1,a_2,\dots,a_n\) 有多少种和小于等于 \(m\) 的方案,方案数对 \(19491001\) 取模。

数据范围:\(1 \le n,m \le 10^{18}\)

Round 5

给定 \(n\),计算:

\[\sum_{i=1}^{n} \sum_{j=1}^{i} [\gcd(i,j)=(i \oplus j)] \]

数据范围:\(1 \le n \le 10^6\)


同时展示了两个题,第一个题还是太简单了。

Sol 4

给诸位投喂一个模板题换换口味。

答案是 \(C_{n+m}^{m} \bmod 19491001\),模数大小区区 \(10^7\),当然可以卢卡斯定理。

Sol 5

重要结论:不妨设 \(a \ge b\),有 \(\gcd(a,b) \le a-b \le a\oplus b\)

\(d=a-b\),枚举 \(d\),枚举 \(d\) 的倍数,每次 \(O(1)\) 判断异或的取等条件,时间复杂度 \(O(n \ln n)\)

原题有多测,还需预处理答案的差分数组;数据范围 \(10^7\),但是时限 \(5s\)


Round 6

给定 \(n\),计算:

\[\sum_{i=1}^{n}\sum_{j=1}^{n}ij\gcd(i,j) \]

数据范围:\(1 \le n \le 10^{10}\)


Sol 6

莫反发力,也有更简单的做法。限于篇幅,这里介绍后者。莫反做法去参考相关题解。

考虑狄利克雷卷积告诉我们的重要结论(在欧拉函数那一部分也出现过了)。

\[\varphi * \operatorname{I} = \operatorname{Id} \]

说人话就是——

\[\sum_{d \mid n} \varphi(d) = n \]

嗯,记住这个式子。


那么,还是对 \(\gcd(i,j)\) 的部分动手术。

\[\sum_{i=1}^{n}\sum_{j=1}^{n}ij \sum_{d \mid \gcd(i,j)} \varphi(d) \]

然后就是经典套路,交换求和顺序,把枚举 \(d\) 丢到前面去,有:

\[\sum_{d=1}^{n} \varphi(d) \sum_{d \mid i}^{n} \sum_{d \mid j}^{n} ij \]

还是经典套路,枚举倍数等价于先把数提出来再枚举“倍”,有:

\[\sum_{d=1}^{n} \varphi(d) \cdot d^2 \sum_{i=1}^{B} \sum_{j=1}^{B} ij \]

其中记 \(B=\lfloor \frac{n}{d} \rfloor\)


继续转化这个式子,先合并,再分裂,有:

\[\Bigg( \sum_{d=1}^{n} \varphi(d) \cdot d^2 \Bigg) \cdot \Bigg(\sum_{d=1}^{n} \Big( \sum_{i=1}^{B} i \Big)^2 \Bigg) \]

后面的可以简单整除分块维护,前面的容易想到杜教筛。

问题转化为如何构造一个合适的数论函数 \(g(d)\),使得可以快速计算 \(f*g\)

为了方便维护,我们肯定不希望 \(f*g\) 的函数内部出现一些神秘的东西,让 \(f*g\) 里只出现变量 \(n\) 应当是上上策。


然后你发现 \(f\) 的后面有个 \(d^2\),尝试构造 \(g\) 把它消掉,比如令 \(g=\operatorname{Id}_2\),因此有:

\[\begin{aligned} \Big( f*g \Big) (n) &= \sum_{d \mid n} (\varphi(d) \cdot d^2)(\frac{n}{d})^2 \\ &= n^2 \sum_{d \mid n} \varphi(d) \\ &= n^3 \end{aligned} \]

好了,求 \(f*g\) 等价于求立方和,求 \(g\) 的前缀和等价于求平方和。

剩下的就是代码实现了,依旧是依照题意写代码。


Round 7

定义 \(f(x)\) 为满足 \(ijk=x\) 的三元组 \((i,j,k)\) 个数。给定 \(n\),求 \(\sum_{i=1}^{n}f(i)\)

数据范围:\(1 \le n \le 10^{10}\)

一题多解,建议深度思考。


Sol 7

  1. 朴素做法(难度:黄)

  2. 数论分块(难度:蓝)

  3. 莫反 \(+\) 杜教筛(难度:紫)


莫比乌斯反演 \(+\) 杜教筛做法

形式化一下目标答案,有:

\[\sum_{i=1}^{n}\sum_{j=1}^{\lfloor \frac{n}{i} \rfloor} \lfloor \frac{N}{ij} \rfloor \]

然后后面这坨可以改写称枚举 \(i\) 的倍数,形如:

\[\sum_{i=1}^{n}\sum_{i \mid x}^{n} \lfloor \frac{n}{x} \rfloor \]


典中典之交换求和号,得:

\[\sum_{x=1}^{n} \sum_{i \mid x} \lfloor \frac{n}{x} \rfloor \]

注意到里面的式子与约数 \(i\) 无关,所以有:

\[\sum_{x=1}^{n}d(x)\lfloor \frac{n}{x} \rfloor \]

其中 \(d(x)\) 表示 \(x\) 的约数个数。


显然可以数论分块,问题转化为快速求 \(d(x)\) 的前缀和。

根据狄利克雷卷积相关内容,有 \(d * \mu = \operatorname{I}\)

那么套一层莫反之后,就得到了 \(d(x)\) 前缀和的式子,如下:

\[\sum_{i=1}^{n} d(i) = n-\sum_{i=2}^{n} \mu(i) d(\frac{n}{i}) \]

嗯?怎么变成莫比乌斯函数的前缀和了?没关系,再来一个杜教筛与数论分块就好了。

时间复杂度 \(O(???)\)

简单的问题复杂化,复杂的问题抽象化,抽象的问题离谱化,离谱的问题____化?


数论分块做法

还是推式子,这次少推一点。

\[\sum_{i=1}^{n} f(i) = \sum_{i=1}^{n}\sum_{x \mid i}d(\frac{i}{x})=\sum_{x=1}^{n}\sum_{i=1}^{\lfloor \frac{n}{x} \rfloor}d(i) \]

经典数论分块的形式,问题又双叒叕转化为了求约数个数函数的前缀和

为了方便表述,记 \(S(n)=\sum_{i=1}^{n} d(i)\)

难道我们又要莫反杜教筛吗?不,我们还有小清新分治做法。


如果 \(n \le 10^7\),可以直接预处理 \(S(n)\)

而如果 \(n>10^7\),你发现可以推式子(依据是 \(\operatorname{I} * \operatorname{I}=d\)),有:

\[\sum_{i=1}^{n} d(i) = \sum_{i=1}^{n} \sum_{x \mid i} 1 = \sum_{x=1}^{n} \lfloor \frac{n}{x} \rfloor \]

然后你大可以对这么个式子数论分块,于是乎就做完了。


朴素做法

啧,考虑对 \((i,j,k)\) 简单分讨(分讨后有序三元组转化为无序三元组)。

  1. \(i \neq j \neq k\),对答案的贡献为 \(6\),枚举 \(i,j\) 即可。

  2. \(i = j \neq k\),枚举 \(i\) 即可。

  3. \(i=j=k\),无需枚举,直接计算贡献。

时间复杂度 \(O(n^{\frac{2}{3}}+n^{\frac{1}{2}}+n^{\frac{0}{1}})\)

真是,难评。


杂《》选吃的题单

P2155
CF1614D2
P3579
P5160
UVA12716
P3768
P10239


完结撒花!

bg right

posted @ 2025-09-09 11:09  sunxuhetai  阅读(5)  评论(0)    收藏  举报