本文承接上文acm-基础数论学习笔记(上),并且正在更新中。

数论:

  • 九、特殊问题
    • 1.约瑟夫环
      • (1).问题引入
      • (2).暴力解法
      • (3).递推解法
      • (4).递推优化
    • 2.斐波拉契数列
      • (1).定义
      • (2).性质
    • 3.佩尔方程
      • (1).定义
      • (2).性质
      • (3).求解方法
        • [1].暴力法
        • [2].连分数法
          • <1>.连分数介绍
          • <2>.应用连分数求解佩尔方程
      • (4).习题
    • 4.类欧几里得算法
      • (1).定义
      • (2).f函数求解
      • (3).h函数求解
      • (4).g函数求解
      • (5).模板总结
      • (6).习题
  • 十、数论函数
    • 1.整除分块
      • (1).引理
      • (2).分块
    • 2.积性函数
      • (1).定义
      • (2).性质
      • (3).常见积性函数
      • (4).线性筛预处理积性函数
        • [1].莫比乌斯函数μ(n)\mathbf{\mu(n)}μ(n)
        • [2].约数个数函数d(n)\mathbf{d(n)}d(n)
        • [3].约数和函数σ(n)\mathbf{\sigma(n)}σ(n)
    • 3.狄利克雷卷积
      • (1).定义
      • (2).性质
      • (3).常用卷积转化关系
    • 4.莫比乌斯反演定理
      • (1).基本内容
      • (2).证明
      • (3).习题
    • 5.特殊筛法
      • (1).杜教筛
        • [1].原理介绍
        • [2].习题
      • (2).min_25筛
        • [1].原理介绍
        • [2].习题
      • (3).洲阁筛
    • 6.推式子综合技巧
  • 总结

九、特殊问题

1.约瑟夫环

(1).问题引入

n个人围成一圈,从第一个人开始报数,数到k的人出列,再由下一个人重新从1开始报数,数到k的人再出圈,依次类推,直到所有的人都出圈,问最后出圈的一个人的编号是多少。

以上是这个问题的大致形式,除了问最后出圈的一个人的编号以外还可以问每次出圈的人的编号是多少。后面主要讨论如何快速确定最后一个出圈的人的编号。

(2).暴力解法

首先考虑最暴力的暴力做法,模拟整个报数的流程,对于当前的人如果已经报过数了就跳过,没报过数就让他报数并且让计数器加一,直到计数器变成k的时候给当前的人打个标记然后归零,直到只剩下一个人未被标记,这个人的编号就是最终的答案。

但上面的写法复杂度达到了下界O(nk)\mathbf{O(nk)}O(nk),考虑如何稍微优化一下,注意到那些被打了标记的人会被重复考虑,这是因为我们没有把它们剔除数组,因为数组元素移动是O(n)\mathbf{O(n)}O(n)的,剔除人就需要移动数组元素,故不合算。考虑适合剔除元素的数据结构,容易想到链表,我们用循环链表模拟这个圈,一旦有人报数为k的时候就把这个人对应的元素从链表中删除即可,这样就避免了报过数的人被重复考虑的冗余过程。

注意到上述两种做法虽然第二种更优秀,但复杂度是相同的,都是O(nk)\mathbf{O(nk)}O(nk),故两者在本质上没有太多区别,不过当问题要求输出每次剔除的人的编号的时候链表模拟也是不错的选择。

(3).递推解法

我们先给位置从0开始标号(方便计算),然后设f(n)\mathbf{f(n)}f(n)是n\mathbf{n}n个人的时候的答案,那么有f(n)=(f(n−1)+k)%n\mathbf{f(n)=(f(n-1)+k)\%n}f(n)=(f(n−1)+k)%n。
如何证明这一结论呢?我们采用映射的办法证明它。
首先最初的时候序列的分布如下所示(蓝色代表即将开始报数的位置):

位置 0 1 2 3 4 c-1 c c+1 n-1
编号 0 1 2 3 4 c-1 c c+1 n-1

然后我们从位置0开始往后数k个人,把第k个人给标记,显然往后数第k个人对应的编号为(k−1)%n\mathbf{(k-1)\%n}(k−1)%n,不妨设c=(k−1)%n\mathbf{c=(k-1)\%n}c=(k−1)%n,我们给编号c打上标记,于是序列分布变成下面的样子(标记成红色代表被踢出圈,蓝色代表即将报数的位置):

位置 0 1 2 3 4 c-1 c c+1 n-1
编号 0 1 2 3 4 c-1 c c+1 n-1

现在c\mathbf{c}c已经被踢出了,并且我们即将从新的起点c+1\mathbf{c+1}c+1开始报数,不妨从c+1\mathbf{c+1}c+1位置开始给所有人安排一个新的编号,即把当前编号映射成新的编号。然后我们对现在的编号做一下映射得到下面的序列:

位置 0 1 2 3 4 c-1 c c+1 c+2 n-1
原编号 0 1 2 3 4 c-1 c c+1 c+2 n-1
映射编号 n-c-1 n-c n-c+1 n-c+2 n-c+3 n-2 - 0 1 n-c-2

根据表格容易发现映射编号与原编号的关系,设s\mathbf{s}s为原编号,s′\mathbf{s'}s′为新编号,则满足:s={s′+c+1,if s′∈[0,n−c−2]s′+c+1−n,if s′∈[n−c−1,n−2]\mathbf{s = \begin{cases} s'+c+1, & \text{if }s'\in[0,n-c-2] \\ s'+c+1-n, & \text{if }s'\in[n-c-1,n-2] \end{cases}}s={s′+c+1,s′+c+1−n,​if s′∈[0,n−c−2]if s′∈[n−c−1,n−2]​
注意到s∈[0,n)\mathbf{s\in[0,n)}s∈[0,n),又(c+1)≡(c+1−n)(modn)\mathbf{(c+1)\equiv (c+1-n)\pmod n}(c+1)≡(c+1−n)(modn),故我们其实可以将映射式改写为s=(s′+c+1)%n\mathbf{s=(s'+c+1)\%n}s=(s′+c+1)%n,这样就统一多了。然后注意到从映射编号对应的0开始报数,最终的映射编号下的答案其实就是f(n−1)\mathbf{f(n-1)}f(n−1),然后我们又有了映射函数,直接映射回去就能得到在序列中的原编号了,也就是f(n)=(f(n−1)+c+1)%n\mathbf{f(n)=(f(n-1)+c+1)\%n}f(n)=(f(n−1)+c+1)%n,由于c=(k−1)%n\mathbf{c=(k-1)\%n}c=(k−1)%n,我们带进去简化一下得到f(n)=(f(n−1)+(k−1)%n+1)%n=(f(n−1)+k)%n\mathbf{f(n)=(f(n-1)+(k-1)\%n+1)\%n=(f(n-1)+k)\%n}f(n)=(f(n−1)+(k−1)%n+1)%n=(f(n−1)+k)%n,这也是我们最终要证明的结论。

此外显然有f(1)=0\mathbf{f(1)=0}f(1)=0,综合一下我们就得到了这个简单的公式:
f(n)={0,if n=1(f(n−1)+k)%n,if n>1\mathbf{f(n) = \begin{cases} 0, & \text{if }n=1 \\ (f(n-1)+k)\%n, & \text{if }n>1 \end{cases}}f(n)={0,(f(n−1)+k)%n,​if n=1if n>1​
于是我们就能做到O(n)\mathbf{O(n)}O(n)递推了。

(4).递推优化

在前面递推地基础上进行简单的推广我们可以得到更优秀的方法。
还是考虑同样的分布:

位置 0 1 2 3 4 c-1 c c+1 n-1
编号 0 1 2 3 4 c-1 c c+1 n-1

刚才我们是k步k步往前报数,这次我们不妨加速这一进程,假设k<n\mathbf{k<n}k<n,我们直接走⌊nk⌋\mathbf{\lfloor \frac nk\rfloor}⌊kn​⌋个k\mathbf{k}k步,这样能够一次性剔除⌊nk⌋\mathbf{\lfloor \frac nk\rfloor}⌊kn​⌋个人,于是就能得到如下表所示的分布(令t=⌊nk⌋\mathbf{t=\lfloor \frac nk\rfloor}t=⌊kn​⌋)。

位置 0 1 2 3 k-1 k 2k-1 2k tk-1 tk n-1
编号 0 1 2 3 k-1 k 2k-1 2k tk-1 tk n-1

我们还是从蓝色的编号开始以它为新起点重新给这些人编号,得到的映射结果如下表所示:

位置 0 1 2 3 k-1 k 2k-1 2k tk-2 tk-1 tk tk+1 n-1
原编号 0 1 2 3 k-1 k 2k-1 2k tk-2 tk-1 tk tk+1 n-1
映射编号 n-tk n-tk+1 n-tk+2 n-tk+3 - n-tk+k-1 - n-tk+2k-2 n-t-1 - 0 1 n-1-tk

根据上面的表格很容易找到映射编号s′\mathbf{s'}s′与原编号s\mathbf{s}s关系:s={s′+tk,if s′∈[0,n−1−tk]s′+tk+⌊s′−(n−tk)k−1⌋−n,if s′∈[n−tk,n−t−1]\mathbf{s = \begin{cases} s'+tk, & \text{if }s'\in[0,n-1-tk] \\ s'+tk+\lfloor \frac{s'-(n-tk)}{k-1}\rfloor-n, & \text{if }s'\in[n-tk,n-t-1] \end{cases}}s={s′+tk,s′+tk+⌊k−1s′−(n−tk)​⌋−n,​if s′∈[0,n−1−tk]if s′∈[n−tk,n−t−1]​
当然你也可以让这个式子对n取模,不影响结果。利用这个映射关系我们就容易得到f(n)\mathbf{f(n)}f(n)的具体表达式,又因为f(1)=0\mathbf{f(1)=0}f(1)=0,此外注意到n−tk=n%k\mathbf{n-tk=n\%k}n−tk=n%k,故我们有:f(n)={0,if n=1(f(n−⌊nk⌋)+⌊nk⌋k)%n,if n>1且f(n−⌊nk⌋)≤n%k−1(f(n−⌊nk⌋)+⌊f(n−⌊nk⌋)−n%kk−1⌋−n%k)%nif n>1且f(n−⌊nk⌋)≥n%k\mathbf{f(n) = \begin{cases} 0, & \text{if }n=1 \\ (f(n-\lfloor \frac{n}{k}\rfloor)+\lfloor \frac{n}{k}\rfloor k)\%n, & \text{if }n>1 \text{且}f(n-\lfloor \frac{n}{k}\rfloor)\le n\%k-1\\ (f(n-\lfloor \frac{n}{k}\rfloor)+\lfloor \frac{f(n-\lfloor \frac{n}{k}\rfloor)-n\%k}{k-1}\rfloor -n\%k)\%n& \text{if }n>1 \text{且}f(n-\lfloor \frac{n}{k}\rfloor)\ge n\%k \end{cases}}f(n)=⎩⎪⎨⎪⎧​0,(f(n−⌊kn​⌋)+⌊kn​⌋k)%n,(f(n−⌊kn​⌋)+⌊k−1f(n−⌊kn​⌋)−n%k​⌋−n%k)%n​if n=1if n>1且f(n−⌊kn​⌋)≤n%k−1if n>1且f(n−⌊kn​⌋)≥n%k​
注意该公式只适用于k<n\mathbf{k<n}k<n的时候,对于k大于等于n的情况我们只能套用前一个递推公式,当然为了美观你也可以写出一个综合的递推式出来:
fk(n)={0,if n=1{(f(n−⌊nk⌋)+⌊nk⌋k)%n,if n>1且f(n−⌊nk⌋)≤n%k−1(f(n−⌊nk⌋)+⌊f(n−⌊nk⌋)−n%kk−1⌋−n%k)%nif n>1且f(n−⌊nk⌋)≥n%kif k<n{(f(n−1)+k)%nif n>1if k≥n\mathbf{f_k(n) = \begin{cases} 0, & \text{if }n=1 \\ \begin{cases} (f(n-\lfloor \frac{n}{k}\rfloor)+\lfloor \frac{n}{k}\rfloor k)\%n, & \text{if }n>1 \text{且}f(n-\lfloor \frac{n}{k}\rfloor)\le n\%k-1\\ (f(n-\lfloor \frac{n}{k}\rfloor)+\lfloor \frac{f(n-\lfloor \frac{n}{k}\rfloor)-n\%k}{k-1}\rfloor -n\%k)\%n& \text{if }n>1 \text{且}f(n-\lfloor \frac{n}{k}\rfloor)\ge n\%k \end{cases} & \text{if } k<n\\ \begin{cases} (f(n-1)+k)\%n & \text{if }n>1 \end{cases}& \text{if }k\ge n \end{cases}}fk​(n)=⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧​0,{(f(n−⌊kn​⌋)+⌊kn​⌋k)%n,(f(n−⌊kn​⌋)+⌊k−1f(n−⌊kn​⌋)−n%k​⌋−n%k)%n​if n>1且f(n−⌊kn​⌋)≤n%k−1if n>1且f(n−⌊kn​⌋)≥n%k​{(f(n−1)+k)%n​if n>1​​if n=1if k<nif k≥n​

复杂度的话,在k<n\mathbf{k<n}k<n的时候可以认为每次递推将n−nk\mathbf{n-\frac nk}n−kn​变成n\mathbf{n}n,也就是乘了个kk−1\mathbf{\frac {k}{k-1}}k−1k​,那么复杂度近似为logkk−1n\mathbf{log_{\frac {k}{k-1}}{n}}logk−1k​​n;在k≥n\mathbf{k\ge n}k≥n的时候复杂度为O(n)\mathbf{O(n)}O(n)。可以发现当k特别小的时候这个算法会非常优秀。

2.斐波拉契数列

(1).定义

斐波拉契数列满足如下递推式
f(n)={0,if n=01,if n=1f(n−1)+f(n−2),if n≥2\mathbf{f(n)=\begin{cases} 0,&\text{if }n=0\\ 1,&\text{if }n=1\\ f(n-1)+f(n-2),&\text{if }n\ge 2 \end{cases}}f(n)=⎩⎪⎨⎪⎧​0,1,f(n−1)+f(n−2),​if n=0if n=1if n≥2​
求解这个数列可以直接递推着求,利用递归写法即可。
不过如果n很大的话就需要用到矩阵快速幂,不明白的可以去网上其它地方查阅资料。

(2).性质

  1. f(n)=15[(1+52)n−(1−52)n]\mathbf{f(n)=\frac{1}{\sqrt 5}[(\frac{1+\sqrt 5}{2})^n-(\frac{1-\sqrt 5}{2})^n]}f(n)=5​1​[(21+5​​)n−(21−5​​)n]。
    证明:这个证明非常神奇,我们可以发现存在a∈R\mathbf{a\in R}a∈R使得g(n)=f(n)−af(n−1)\mathbf{g(n)=f(n)-af(n-1)}g(n)=f(n)−af(n−1)成为一个等比数列,然后就证明完毕了…可能有点懵,这里详细解释一下,我们尝试着找到这个a\mathbf{a}a,不妨设g(n)=bg(n−1)\mathbf{g(n)=bg(n-1)}g(n)=bg(n−1),展开有f(n)−af(n−1)=bf(n−1)−baf(n−2)\mathbf{f(n)-af(n-1)=bf(n-1)-baf(n-2)}f(n)−af(n−1)=bf(n−1)−baf(n−2),移项得到f(n)=(a+b)f(n−1)−baf(n−2)\mathbf{f(n)=(a+b)f(n-1)-baf(n-2)}f(n)=(a+b)f(n−1)−baf(n−2),又根据定义有f(n)=f(n−1)+f(n−2)\mathbf{f(n)=f(n-1)+f(n-2)}f(n)=f(n−1)+f(n−2),于是能够得到a+b=1,ab=−1\mathbf{a+b=1,ab=-1}a+b=1,ab=−1,解方程容易发现解为1±52\mathbf{\frac{1\pm \sqrt 5}{2}}21±5​​(因此有两组解),又因为g(1)=f(1)−f(0)=1\mathbf{g(1)=f(1)-f(0)=1}g(1)=f(1)−f(0)=1,知道首项和公比,那么就是常规等比数列的通项求解了,容易得到g(n)=bn−1⇒f(n)=bn−1+af(n−1)\mathbf{g(n)=b^{n-1}\Rightarrow f(n)=b^{n-1}+af(n-1)}g(n)=bn−1⇒f(n)=bn−1+af(n−1),将两组解代入这个式子得到:
    f(n)=(1−52)n−1+(1+52)f(n−1)\mathbf{f(n)={(\frac{1-\sqrt 5}{2})}^{n-1}+(\frac{1+\sqrt 5}2)f(n-1)}f(n)=(21−5​​)n−1+(21+5​​)f(n−1)
    f(n)=(1+52)n−1+(1−52)f(n−1)\mathbf{f(n)={(\frac{1+\sqrt 5}{2})}^{n-1}+(\frac{1-\sqrt 5}2)f(n-1)}f(n)=(21+5​​)n−1+(21−5​​)f(n−1)
    将f(n)与f(n−1)\mathbf{f(n)与f(n-1)}f(n)与f(n−1)看做未知数,这就成了一个二元一次方程问题,解一下就能得到f(n)=15[(1+52)n−(1−52)n]\mathbf{f(n)=\frac{1}{\sqrt 5}[(\frac{1+\sqrt 5}{2})^n-(\frac{1-\sqrt 5}{2})^n]}f(n)=5​1​[(21+5​​)n−(21−5​​)n]。

  2. f(1)+f(2)+...+f(n)=f(n+2)−1\mathbf{f(1)+f(2)+...+f(n)=f(n+2)-1}f(1)+f(2)+...+f(n)=f(n+2)−1。
    证明:f(1)=f(3)−f(2)\mathbf{f(1)=f(3)-f(2)}f(1)=f(3)−f(2)
    f(2)=f(4)−f(3)\mathbf{f(2)=f(4)-f(3)}f(2)=f(4)−f(3)
    f(3)=f(5)−f(4)\mathbf{f(3)=f(5)-f(4)}f(3)=f(5)−f(4)

    f(n)=f(n+2)−f(n−1)\mathbf{f(n)=f(n+2)-f(n-1)}f(n)=f(n+2)−f(n−1)
    将式子全部加起来得到∑i=1nf(i)=f(n+2)−f(2)=f(n+2)−1\mathbf{\sum_{i=1}^{n}f(i)=f(n+2)-f(2)=f(n+2)-1}∑i=1n​f(i)=f(n+2)−f(2)=f(n+2)−1。

  3. f(1)2+f(2)2+...+f(n)2=f(n)f(n+1)\mathbf{f(1)^2+f(2)^2+...+f(n)^2=f(n)f(n+1)}f(1)2+f(2)2+...+f(n)2=f(n)f(n+1)。
    证明:首先得到f(1)2+f(2)2=1+1=2=f(2)f(3)\mathbf{f(1)^2+f(2)^2=1+1=2=f(2)f(3)}f(1)2+f(2)2=1+1=2=f(2)f(3),然后我们就可以列出如下式子:
    (f(1)2+f(2)2)+f(3)2=f(2)f(3)+f(3)2=f(3)[f(2)+f(3)]=f(3)f(4)\mathbf{(f(1)^2+f(2)^2)+f(3)^2=f(2)f(3)+f(3)^2=f(3)[f(2)+f(3)]=f(3)f(4)}(f(1)2+f(2)2)+f(3)2=f(2)f(3)+f(3)2=f(3)[f(2)+f(3)]=f(3)f(4)
    (f(1)2+f(2)2+f(3)2)+f(4)2=f(3)f(4)+f(4)2=f(4)[f(3)+f(4)]=f(4)f(5)\mathbf{(f(1)^2+f(2)^2+f(3)^2)+f(4)^2=f(3)f(4)+f(4)^2=f(4)[f(3)+f(4)]=f(4)f(5)}(f(1)2+f(2)2+f(3)2)+f(4)2=f(3)f(4)+f(4)2=f(4)[f(3)+f(4)]=f(4)f(5)

    f(1)2+f(2)2+...+f(n)2=f(n)f(n+1)\mathbf{f(1)^2+f(2)^2+...+f(n)^2=f(n)f(n+1)}f(1)2+f(2)2+...+f(n)2=f(n)f(n+1)
    证毕。

  4. f(1)+f(3)+f(5)+...+f(2n−1)=f(2n)\mathbf{f(1)+f(3)+f(5)+...+f(2n-1)=f(2n)}f(1)+f(3)+f(5)+...+f(2n−1)=f(2n)。
    证明:像性质2的证明过程一样展开即可。
    f(1)=f(2)−f(0)\mathbf{f(1)=f(2)-f(0)}f(1)=f(2)−f(0)
    f(3)=f(4)−f(2)\mathbf{f(3)=f(4)-f(2)}f(3)=f(4)−f(2)

    f(2n−1)=f(2n)−f(2n−2)\mathbf{f(2n-1)=f(2n)-f(2n-2)}f(2n−1)=f(2n)−f(2n−2)
    将式子全部加起来得到∑i=1nf(2i−1)=f(2n)−f(0)=f(2n)\mathbf{\sum_{i=1}^nf(2i-1)=f(2n)-f(0)=f(2n)}∑i=1n​f(2i−1)=f(2n)−f(0)=f(2n)

  5. f(2)+f(4)+f(6)+...+f(2n)=f(2n+1)−1\mathbf{f(2)+f(4)+f(6)+...+f(2n)=f(2n+1)-1}f(2)+f(4)+f(6)+...+f(2n)=f(2n+1)−1。
    证明:跟性质4证明过程几乎完全一样。
    f(2)=f(3)−f(1)\mathbf{f(2)=f(3)-f(1)}f(2)=f(3)−f(1)
    f(4)=f(5)−f(3)\mathbf{f(4)=f(5)-f(3)}f(4)=f(5)−f(3)

    f(2n)=f(2n+1)−f(2n−1)\mathbf{f(2n)=f(2n+1)-f(2n-1)}f(2n)=f(2n+1)−f(2n−1)
    将式子加起来得到∑i=1nf(2i)=f(2n+1)−f(1)=f(2n+1)−1\mathbf{\sum_{i=1}^nf(2i)=f(2n+1)-f(1)=f(2n+1)-1}∑i=1n​f(2i)=f(2n+1)−f(1)=f(2n+1)−1

  6. f(n)=f(m)f(n−m+1)+f(m−1)f(n−m),n≥m≥1\mathbf{f(n)=f(m)f(n-m+1)+f(m-1)f(n-m),n\ge m \ge 1}f(n)=f(m)f(n−m+1)+f(m−1)f(n−m),n≥m≥1
    证明:还是列式子找规律吧…
    f(n)=1⋅f(n)+0\mathbf{f(n)=1\cdot f(n)+0}f(n)=1⋅f(n)+0
    f(n)=f(n−1)+f(n−2)\mathbf{f(n)=f(n-1)+f(n-2)}f(n)=f(n−1)+f(n−2)
    f(n)=2f(n−2)+f(n−3)\mathbf{f(n)=2f(n-2)+f(n-3)}f(n)=2f(n−2)+f(n−3)
    f(n)=3f(n−3)+2f(n−4)\mathbf{f(n)=3f(n-3)+2f(n-4)}f(n)=3f(n−3)+2f(n−4)

    我们设f(n)=ai+1f(n−i)+bif(n−i−1),i≥0\mathbf{f(n)=a_{i+1}f(n-i)+b_if(n-i-1),i\ge 0}f(n)=ai+1​f(n−i)+bi​f(n−i−1),i≥0,很根据上面列的式子容易发现ai和bi\mathbf{a_i和b_i}ai​和bi​之间的联系,它们满足ai+1=ai+bi−1,bi=ai⇒ai+1=ai+ai−1\mathbf{a_{i+1}=a_i+b_{i-1},b_{i}=a_{i}\Rightarrow a_{i+1}=a_i+a_{i-1}}ai+1​=ai​+bi−1​,bi​=ai​⇒ai+1​=ai​+ai−1​,再结合a2=1,a1=b1=1⇒\mathbf{a_2=1,a_1=b_1=1\Rightarrow}a2​=1,a1​=b1​=1⇒我们发现ai\mathbf{a_i}ai​就是一个斐波拉契数列,干脆将ai\mathbf{a_i}ai​写为f(i)\mathbf{f(i)}f(i),于是有f(n)=f(i+1)f(n−i)+f(i)f(n−i−1)\mathbf{f(n)=f(i+1)f(n-i)+f(i)f(n-i-1)}f(n)=f(i+1)f(n−i)+f(i)f(n−i−1),令m=i+1\mathbf{m=i+1}m=i+1我们就能得到f(n)=f(m)f(n−m+1)+f(m−1)f(n−m)\mathbf{f(n)=f(m)f(n-m+1)+f(m-1)f(n-m)}f(n)=f(m)f(n−m+1)+f(m−1)f(n−m),其中n≥m≥1\mathbf{n\ge m\ge 1}n≥m≥1。
    ps:该式子也常常写作f(n+m)=f(m−1)f(n)+f(m)f(n+1)\mathbf{f(n+m)=f(m-1)f(n)+f(m)f(n+1)}f(n+m)=f(m−1)f(n)+f(m)f(n+1)

  7. f(n−1)f(n+1)=f(n)2+(−1)n\mathbf{f(n-1)f(n+1)=f(n)^2+(-1)^n}f(n−1)f(n+1)=f(n)2+(−1)n。
    证明:我们只需要证明到这个式子满足斐波拉契数列的定义即可,也就是说满足∀n≥2有f(n)=f(n−1)+f(n−2)\mathbf{\forall n\ge2有f(n)=f(n-1)+f(n-2)}∀n≥2有f(n)=f(n−1)+f(n−2)即可,我们采用数学归纳法证明这一点。
    首先我们令f(2)=1,f(1)=1,f(0)=0\mathbf{f(2)=1,f(1)=1,f(0)=0}f(2)=1,f(1)=1,f(0)=0,当n=1\mathbf{n=1}n=1时代入式子有f(0)f(2)=f(1)2+(−1)1\mathbf{f(0)f(2)=f(1)^2+(-1)^1}f(0)f(2)=f(1)2+(−1)1显然是正确的。
    然后当n=2\mathbf{n=2}n=2时有f(1)f(3)=f(2)2+(−1)2⇒f(3)=2\mathbf{f(1)f(3)=f(2)^2+(-1)^2\Rightarrow f(3)=2}f(1)f(3)=f(2)2+(−1)2⇒f(3)=2,符合f(3)=f(2)+f(1)\mathbf{f(3)=f(2)+f(1)}f(3)=f(2)+f(1)的递推定义。
    现在假设n=k\mathbf{n=k}n=k的时候该式子符合斐波拉契数列递推式,也就是能够推出f(k+1)=f(k)+f(k−1)\mathbf{f(k+1)=f(k)+f(k-1)}f(k+1)=f(k)+f(k−1),那先把该式子代入f(n−1)f(n+1)=f(n)2+(−1)n\mathbf{f(n-1)f(n+1)=f(n)^2+(-1)^n}f(n−1)f(n+1)=f(n)2+(−1)n中得到f(k−1)f(k+1)=f(k)2+(−1)k⇒f(k−1)f(k)+f(k−1)2=f(k)2+(−1)k\mathbf{f(k-1)f(k+1)=f(k)^2+(-1)^k\Rightarrow f(k-1)f(k)+f(k-1)^2=f(k)^2+(-1)^k}f(k−1)f(k+1)=f(k)2+(−1)k⇒f(k−1)f(k)+f(k−1)2=f(k)2+(−1)k(①式),又因为当n=k+1\mathbf{n=k+1}n=k+1时候有f(k+2)f(k)=f(k+1)2+(−1)k+1\mathbf{f(k+2)f(k)=f(k+1)^2+(-1)^{k+1}}f(k+2)f(k)=f(k+1)2+(−1)k+1,移项后有f(k+2)=f(k+1)2+(−1)k+1f(k)=f(k)2+2f(k)f(k−1)+f(k−1)2+(−1)k+1f(k)\mathbf{f(k+2)=\frac{f(k+1)^2+(-1)^{k+1}}{f(k)}=\frac{f(k)^2+2f(k)f(k-1)+f(k-1)^2+(-1)^{k+1}}{f(k)}}f(k+2)=f(k)f(k+1)2+(−1)k+1​=f(k)f(k)2+2f(k)f(k−1)+f(k−1)2+(−1)k+1​,代入①式 得到f(k+2)=f(k)2+2f(k)f(k−1)+f(k)2+(−1)k−f(k)f(k−1)+(−1)k+1f(k)\mathbf{f(k+2)=\frac{f(k)^2+2f(k)f(k-1)+f(k)^2+(-1)^k-f(k)f(k-1)+(-1)^{k+1}}{f(k)}}f(k+2)=f(k)f(k)2+2f(k)f(k−1)+f(k)2+(−1)k−f(k)f(k−1)+(−1)k+1​,整理一下得到f(k+2)=2f(k)2+f(k)f(k−1)f(k)=2f(k)+f(k−1)=f(k)+f(k+1)\mathbf{f(k+2)=\frac{2f(k)^2+f(k)f(k-1)}{f(k)}=2f(k)+f(k-1)=f(k)+f(k+1)}f(k+2)=f(k)2f(k)2+f(k)f(k−1)​=2f(k)+f(k−1)=f(k)+f(k+1),于是我们知道在n=k+1\mathbf{n=k+1}n=k+1的时候原命题也能够推导出斐波拉契递推式,根据数学归纳法斐波拉契数列具有原命题公式的性质。

  8. 斐波拉契数列相邻两项互素,即满足gcd(f(n),f(n+1))=1\mathbf{gcd(f(n),f(n+1))=1}gcd(f(n),f(n+1))=1。
    证明:gcd(f(n),f(n+1))=gcd(f(n),f(n)+f(n−1))=gcd(f(n−1),f(n))=gcd(f(n−1),f(n−1)+f(n−2))=gcd(f(n−2),f(n−1))=...=gcd(f(1),f(1)+f(0))=gcd(f(0),f(1))=gcd(0,1)=1\mathbf{\begin{aligned} gcd(f(n),f(n+1)) & = gcd(f(n),f(n)+f(n-1))=gcd(f(n-1),f(n)) \\ & = gcd(f(n-1),f(n-1)+f(n-2))=gcd(f(n-2),f(n-1)) \\ & = ... \\ & = gcd(f(1),f(1)+f(0))=gcd(f(0),f(1))=gcd(0,1)=1 \\ \end{aligned}}gcd(f(n),f(n+1))​=gcd(f(n),f(n)+f(n−1))=gcd(f(n−1),f(n))=gcd(f(n−1),f(n−1)+f(n−2))=gcd(f(n−2),f(n−1))=...=gcd(f(1),f(1)+f(0))=gcd(f(0),f(1))=gcd(0,1)=1​

  9. gcd(f(n),f(m))=f(gcd(n,m))\mathbf{gcd(f(n),f(m))=f(gcd(n,m))}gcd(f(n),f(m))=f(gcd(n,m))。
    证明:首先容易验证n=0或m=0\mathbf{n=0或m=0}n=0或m=0命题是正确的,现在假设n≥m≥1\mathbf{n\ge m\ge 1}n≥m≥1,那么根据性质6我们有:
    gcd(f(n),f(m))=gcd(f(m)f(n−m+1)+f(m−1)f(n−m),f(m))=gcd(f(m−1)f(n−m),f(m))=gcd(f(n−m),f(m))........根据性质8由于gcd(f(m−1),f(m))=1=gcd(f(n%m),f(m))=gcd(f(n%m),f(m%(n%m)))=gcd(f(n%(m%(n%m)))),f(m%(n%m)))=...(这个过程与求gcd的过程是一样的)=gcd(f(0),f(gcd(n,m)))=gcd(0,f(gcd(n,m)))=f(gcd(n,m))\mathbf{\begin{aligned} gcd(f(n),f(m)) & = gcd(f(m)f(n-m+1)+f(m-1)f(n-m),f(m)) \\ & = gcd(f(m-1)f(n-m),f(m)) \\ & = gcd(f(n-m),f(m))........根据性质8由于gcd(f(m-1),f(m))=1\\ & = gcd(f(n\%m),f(m)) \\ & = gcd(f(n\%m),f(m\%(n\%m))) \\ & = gcd(f(n\%(m\%(n\%m)))),f(m\%(n\%m))) \\ & = ...(这个过程与求gcd的过程是一样的)\\ & = gcd(f(0),f(gcd(n,m)))=gcd(0,f(gcd(n,m)))=f(gcd(n,m))\\ \end{aligned}}gcd(f(n),f(m))​=gcd(f(m)f(n−m+1)+f(m−1)f(n−m),f(m))=gcd(f(m−1)f(n−m),f(m))=gcd(f(n−m),f(m))........根据性质8由于gcd(f(m−1),f(m))=1=gcd(f(n%m),f(m))=gcd(f(n%m),f(m%(n%m)))=gcd(f(n%(m%(n%m)))),f(m%(n%m)))=...(这个过程与求gcd的过程是一样的)=gcd(f(0),f(gcd(n,m)))=gcd(0,f(gcd(n,m)))=f(gcd(n,m))​
    由于n与m地位对等,故当m≥n≥1\mathbf{m\ge n\ge 1}m≥n≥1时命题也正确,故原命题正确。

  10. n∣m⇔f(n)∣f(m)\mathbf{n\mid m\Leftrightarrow f(n)\mid f(m)}n∣m⇔f(n)∣f(m)。
    证明:若n∣m\mathbf{n\mid m}n∣m,根据性质9,则gcd(f(n),f(m))=f(gcd(n,m))=f(n)⇒f(n)∣f(m)\mathbf{gcd(f(n),f(m))=f(gcd(n,m))=f(n)\Rightarrow f(n)\mid f(m)}gcd(f(n),f(m))=f(gcd(n,m))=f(n)⇒f(n)∣f(m);
    若f(n)∣f(m)\mathbf{f(n)\mid f(m)}f(n)∣f(m),根据性质9,则gcd(f(n),f(m))=f(n)=f(gcd(n,m))⇒n=gcd(n,m)⇒n∣m\mathbf{gcd(f(n),f(m))=f(n)=f(gcd(n,m))\Rightarrow n=gcd(n,m)\Rightarrow n\mid m}gcd(f(n),f(m))=f(n)=f(gcd(n,m))⇒n=gcd(n,m)⇒n∣m;
    综上原命题正确。

  11. 若x∣f(n)\mathbf{x\mid f(n)}x∣f(n),则x∣f(kn)\mathbf{x\mid f(kn)}x∣f(kn)。
    证明:根据性质9我们有gcd(f(n),f(kn))=f(n)\mathbf{gcd(f(n),f(kn))=f(n)}gcd(f(n),f(kn))=f(n),易知原命题正确。

  12. 设数列an+1=1+an,a1=1\mathbf{a_{n+1}=1+a_n,a_1=1}an+1​=1+an​,a1​=1,那么an\mathbf{a_n}an​的通项公式an=f(n+1)f(n)\mathbf{a_n=\frac{f(n+1)}{f(n)}}an​=f(n)f(n+1)​。
    证明:代入验证即可。

  13. f(2n)=f(n+1)2−f(n−1)2\mathbf{f(2n)=f(n+1)^2-f(n-1)^2}f(2n)=f(n+1)2−f(n−1)2。
    证明:结合性质6我们进行展开即可。
    f(n+1)2−f(n−1)2=[f(n)+f(n−1)]2−f(n−1)2=f(n)2+2f(n)f(n−1)=f(n)[f(n)+f(n−1)+f(n−1)]=f(n)[f(n+1)+f(n−1)]=f(n)f(n+1)+f(n−1)f(n).....结合性质6我们推出下面的式子=f(2n)\mathbf{\begin{aligned} f(n+1)^2-f(n-1)^2 &= [f(n)+f(n-1)]^2-f(n-1)^2\\ &= f(n)^2+2f(n)f(n-1)\\ &=f(n)[f(n)+f(n-1)+f(n-1)]\\ &=f(n)[f(n+1)+f(n-1)]\\ &=f(n)f(n+1)+f(n-1)f(n).....结合性质6我们推出下面的式子\\ &=f(2n) \end{aligned} }f(n+1)2−f(n−1)2​=[f(n)+f(n−1)]2−f(n−1)2=f(n)2+2f(n)f(n−1)=f(n)[f(n)+f(n−1)+f(n−1)]=f(n)[f(n+1)+f(n−1)]=f(n)f(n+1)+f(n−1)f(n).....结合性质6我们推出下面的式子=f(2n)​

  14. 3f(n)=f(n+2)+f(n−2)\mathbf{3f(n)=f(n+2)+f(n-2)}3f(n)=f(n+2)+f(n−2)。
    证明:直接代入递推式即可。
    f(n+2)+f(n−2)=f(n+1)+f(n)+f(n)−f(n−1)=2f(n)+f(n+1)−f(n−1)=2f(n)+f(n)=3f(n)\mathbf{\begin{aligned} f(n+2)+f(n-2)&= f(n+1)+f(n)+f(n)-f(n-1)\\ &= 2f(n)+f(n+1)-f(n-1)\\ &= 2f(n)+f(n)=3f(n) \end{aligned} }f(n+2)+f(n−2)​=f(n+1)+f(n)+f(n)−f(n−1)=2f(n)+f(n+1)−f(n−1)=2f(n)+f(n)=3f(n)​

  15. f(n+1)\mathbf{f(n+1)}f(n+1)等于序列1,2,3,...,n\mathbf{1,2,3,...,n}1,2,3,...,n的所有为不含相邻整数的子集的个数。(其中n=0\mathbf{n=0}n=0的时候代表空集)
    证明:首先当n≤2\mathbf{n\le 2}n≤2的时候容易验证结论成立,现在考虑n>2\mathbf{n>2}n>2的时候,我们可以将序列1,3,4,...,n\mathbf{1,3,4,...,n}1,3,4,...,n的子集分为包含n\mathbf{n}n和不包含n\mathbf{n}n的子集,对于不包含n\mathbf{n}n的子集(不含相邻整数)的个数一定是f(n)\mathbf{f(n)}f(n),而对于包含n\mathbf{n}n的子集由于要求不含相邻整数故不能含有n−1\mathbf{n-1}n−1,故只能在1,2,3,..,n−2\mathbf{1,2,3,..,n-2}1,2,3,..,n−2中选择剩下的元素,故有f(n−1)\mathbf{f(n-1)}f(n−1)种,综上f(n+1)=f(n)+f(n−1)\mathbf{f(n+1)=f(n)+f(n-1)}f(n+1)=f(n)+f(n−1),而这恰好符合斐波拉契的递推式。

  16. 斐波拉契数列中相邻两项的前项比后项的极限是5−12\mathbf{\frac{\sqrt 5-1}2}25​−1​。
    证明:考虑f(n)f(n+1)=15[(1+52)n−(1−52)n]15[(1+52)n+1−(1−52)n+1]=1−(1−51+5)n1+52(1−(1−51+5)n)=1−(1−51+5)n1−(1−51+5)n⋅5−12\mathbf{\frac{f(n)}{f(n+1)}=\frac{\frac{1}{\sqrt 5}[(\frac{1+\sqrt 5}{2})^n-(\frac{1-\sqrt 5}{2})^n]}{\frac{1}{\sqrt 5}[(\frac{1+\sqrt 5}{2})^{n+1}-(\frac{1-\sqrt 5}{2})^{n+1}]}=\frac{1-{(\frac{1-\sqrt 5}{1+\sqrt 5})}^n}{\frac{1+\sqrt 5}2{(1-{(\frac{1-\sqrt 5}{1+\sqrt 5})}^n)}}=\frac{1-{(\frac{1-\sqrt 5}{1+\sqrt 5})}^n}{{1-{(\frac{1-\sqrt 5}{1+\sqrt 5})}^n}}\cdot \frac{\sqrt 5-1}{2}}f(n+1)f(n)​=5​1​[(21+5​​)n+1−(21−5​​)n+1]5​1​[(21+5​​)n−(21−5​​)n]​=21+5​​(1−(1+5​1−5​​)n)1−(1+5​1−5​​)n​=1−(1+5​1−5​​)n1−(1+5​1−5​​)n​⋅25​−1​,容易看出当n→+∞\mathbf{n\rightarrow +∞}n→+∞时极限是5−12\mathbf{\frac{\sqrt 5 -1}{2}}25​−1​。

  17. gcd(f(n+m),f(n))=gcd(f(n),f(m))\mathbf{gcd(f(n+m),f(n))=gcd(f(n),f(m))}gcd(f(n+m),f(n))=gcd(f(n),f(m))。
    证明:结合性质6和性质8容易证明。
    gcd(f(n+m),f(n))=gcd(f(m)f(n+1)+f(m−1)f(n),f(m))=gcd(f(m−1)f(n),f(m))....再根据性质8有下面式子=gcd(f(n),f(m))\mathbf{\begin{aligned} gcd(f(n+m),f(n))&=gcd(f(m)f(n+1)+f(m-1)f(n),f(m))\\ &=gcd(f(m-1)f(n),f(m))....再根据性质8有下面式子\\ &=gcd(f(n),f(m)) \end{aligned} }gcd(f(n+m),f(n))​=gcd(f(m)f(n+1)+f(m−1)f(n),f(m))=gcd(f(m−1)f(n),f(m))....再根据性质8有下面式子=gcd(f(n),f(m))​

  18. f(1)+2f(2)+3f(3)+...+nf(n)=nf(n+2)−f(n+3)+2\mathbf{f(1)+2f(2)+3f(3)+...+nf(n)=nf(n+2)-f(n+3)+2}f(1)+2f(2)+3f(3)+...+nf(n)=nf(n+2)−f(n+3)+2。
    证明:

  19. 斐波拉契数列模一个数具有周期性,如果模n\mathbf{n}n的话每个周期中的元素个数不会超过n⋅n\mathbf{n\cdot n}n⋅n个。

  20. f(2n)f(n)=f(n−1)+f(n+1)\mathbf{\frac{f(2n)}{f(n)}=f(n-1)+f(n+1)}f(n)f(2n)​=f(n−1)+f(n+1)
    证明:结合性质6我们容易证明f(n)[f(n+1)+f(n−1)]=f(n)f(n+1)+f(n−1)f(n)=f(2n)\mathbf{f(n)[f(n+1)+f(n-1)] =f(n)f(n+1)+f(n-1)f(n)=f(2n)}f(n)[f(n+1)+f(n−1)]=f(n)f(n+1)+f(n−1)f(n)=f(2n)。

  21. f(2n−2m−2)[f(2n)+f(2n+2)]=f(2m+2)+f(4n−2m),(n>m≥−1,且n≥1)\mathbf{f(2n-2m-2)[f(2n)+f(2n+2)]=f(2m+2)+f(4n-2m) ,( n>m\ge-1,且n\ge1)}f(2n−2m−2)[f(2n)+f(2n+2)]=f(2m+2)+f(4n−2m),(n>m≥−1,且n≥1)

  22. 斐波拉契数列的最后一位数,最后两位数,最后三位数,最后四位数,最后五位数都具有周期性,分别是:60,300,1500,15000,150000。

  23. 如下图所示,杨辉三角写成下图所示后斜对角线上元素之和构成斐波拉契数列。

  24. 斐波拉契数列的平方和可以用若干个正方形拼成的矩形来表示,其中正方形的边长是斐波拉契数列的值,面积代表项的平方,拼成的矩形代表斐波拉契数列平方和。容易从图中得出性质3是正确的。

  25. 任何一个正整数都可以被唯一地表示成斐波拉契数列中的不相邻项之和。(齐肯多夫定理)
    证明:假设我们要表示x\mathbf{x}x,那么找到一个最大的n使得f(n)≤x<f(n+1)\mathbf{f(n)\le x<f(n+1)}f(n)≤x<f(n+1)成立,那么一定有x<f(n+1)=f(n)+f(n−1)⇒x−f(n)<f(n−1)\mathbf{x<f(n+1)=f(n)+f(n-1)\Rightarrow x-f(n)<f(n-1)}x<f(n+1)=f(n)+f(n−1)⇒x−f(n)<f(n−1),x可以被写成x=f(n)+s\mathbf{x=f(n)+s}x=f(n)+s的形式,并且s<f(n−1)\mathbf{s<f(n-1)}s<f(n−1),意味着s中不可能存在与f(n)\mathbf{f(n)}f(n)相邻的项,我们对s做同样的操作,一直到x\mathbf{x}x被完整表示出来为止,根据刚才的推导显然这些项中没有相邻项。

  26. 模n意义下的斐波拉契数列的周期不会超过6n(皮萨诺周期)。
    证明:较复杂,具体证明在这里。

注意性质1是一个非常有用的性质,虽然里面有根号,但是在遇到取模问题的时候我们可以利用二次剩余来处理这个表达式。

3.佩尔方程

(1).定义

关于整数解的不定方程x2−dy2=1,d>0\mathbf{x^2-dy^2=1,d>0}x2−dy2=1,d>0被称为是佩尔方程。
关于整数解的不定方程x2−dy2=k,k≠1,d>0\mathbf{x^2-dy^2=k,k\ne 1,d>0}x2−dy2=k,k​=1,d>0则被称为是佩尔型方程。
一般情况下二元二次不定方程都能化为佩尔方程的形式,在有些题目中会涉及到佩尔方程的求解。

(2).性质

对于佩尔方程x2−dy2=1\mathbf{x^2-dy^2=1}x2−dy2=1而言,当d\mathbf{d}d是一个平方数的时候我们容易求得方程的解,即x2−(d)2y2=(x−dy)(x+dy)=1⇒{x−dy=1,x+dy=1x−dy=−1,x+dy=−1⇒{x=±1y=0\mathbf{x^2-(\sqrt d)^2y^2=(x-\sqrt dy)(x+\sqrt d y)=1\Rightarrow \begin{cases} x-\sqrt dy &= 1,x+\sqrt dy &=1 \\ x-\sqrt dy &= -1,x+\sqrt dy &=-1 \end{cases}\Rightarrow \begin{cases}x=\pm 1\\ y=0\end{cases} }x2−(d​)2y2=(x−d​y)(x+d​y)=1⇒{x−d​yx−d​y​=1,x+d​y=−1,x+d​y​=1=−1​⇒{x=±1y=0​。
当d\mathbf{d}d是一个非平方数的时候,可以证明该方程存在无限多个整数解,由于正数解和负数解的绝对值都是一样的,故我们这里只讨论正数解,负数解就是正数解加个负号,设x1,y1\mathbf{x_1,y_1}x1​,y1​是它的最小正整数解,那么可以写出其通解的公式,(xnyn)=(x1dy1y1x1)n−1⋅(x1y1)\mathbf{\begin{pmatrix}x_n\\y_n\end {pmatrix}=\begin{pmatrix}x_1 & dy_1\\y_1 & x_1\end{pmatrix}^{n-1}\cdot \begin{pmatrix}x_1\\y_1\end{pmatrix}}(xn​yn​​)=(x1​y1​​dy1​x1​​)n−1⋅(x1​y1​​),我们考虑用数学归纳法证明它确实是佩尔方程的解(至于如何证是个通解感兴趣的可以去网上找相关资料),首先x2=x12+dy12,y2=2x1y1\mathbf{x_2=x_1^2+dy_1^2,y_2=2x_1y_1}x2​=x12​+dy12​,y2​=2x1​y1​,代入佩尔方程得到x22−dy22=(x12+dy12)2−d(2x1y1)2=(x12−dy12)2=1\mathbf{x_2^2-dy_2^2=(x_1^2+dy_1^2)^2-d(2x_1y_1)^2=(x_1^2-dy_1^2)^2=1}x22​−dy22​=(x12​+dy12​)2−d(2x1​y1​)2=(x12​−dy12​)2=1,因此x2,y2\mathbf{x_2,y_2}x2​,y2​是方程的一个解,假设xk,yk\mathbf{x_k,y_k}xk​,yk​是方程的一个解,则xk+12−dyk+12=(x1xk+dy1yk)2−d(y1xk+x1yk)2=x12xk2+d2y12yk2+2dx1y1xkyk−d(y12xk2+x12yk2+2x1y1xkyk)=(xk2−dyk2)(x12−dy12)=1\mathbf{x_{k+1}^2-dy_{k+1}^2=(x_1x_k+dy_1y_k)^2-d(y_1x_k+x_1y_k)^2=x_1^2x_k^2+d^2y_1^2y_k^2+2dx_1y_1x_ky_k-d(y_1^2x_k^2+x_1^2y_k^2+2x_1y_1x_ky_k)=(x_k^2-dy_k^2)(x_1^2-dy_1^2)=1}xk+12​−dyk+12​=(x1​xk​+dy1​yk​)2−d(y1​xk​+x1​yk​)2=x12​xk2​+d2y12​yk2​+2dx1​y1​xk​yk​−d(y12​xk2​+x12​yk2​+2x1​y1​xk​yk​)=(xk2​−dyk2​)(x12​−dy12​)=1,因此xk+1,yk+1\mathbf{x_{k+1},y_{k+1}}xk+1​,yk+1​也是佩尔方程的一个解。
除了将解的递推关系写成矩阵形式,我们也可以写成xn+ynd=(x1+y1d)n,n≥0\mathbf{x_n+y_n\sqrt d=(x_1+y_1\sqrt d)^n,n\ge 0}xn​+yn​d​=(x1​+y1​d​)n,n≥0的形式,这样套一个二次域快速幂即可快速求解任意通解了。

对于佩尔型方程x2−dy2=−1\mathbf{x^2-dy^2=-1}x2−dy2=−1(准确来说叫第II型佩尔方程)而言若方程有解,则假设它的最小正整数解为x1,y1\mathbf{x_1,y_1}x1​,y1​,那么通解可以写成xn+ynd=(x1+y1d)2n+1,n≥0\mathbf{x_n+y_n\sqrt d=(x_1+y_1\sqrt d)^{2n+1},n\ge 0}xn​+yn​d​=(x1​+y1​d​)2n+1,n≥0,但对于该方程想要判断它是否有解非常困难,这里给出oeis上的关于使得该方程有解的n的序列oeis:A031396: 1, 2, 5, 10, 13, 17, 26, 29, 37, 41, 50, 53, 58, 61, 65, 73, 74…,一般来说直接查表即可判断该佩尔型方程是否有解。

此外还有一种佩尔型方程x2−dy2=k,∣k∣>1\mathbf{x^2-dy^2=k,|k|>1 }x2−dy2=k,∣k∣>1就更加复杂了(关于有解判定感兴趣的上网查资料),我们考虑一般的佩尔方程x2−dy2=1\mathbf{x^2-dy^2=1}x2−dy2=1的解为(r,s)\mathbf{(r,s)}(r,s),考虑将x2−dy2=k与r2−ds2=1\mathbf{x^2-dy^2=k与r^2-ds^2=1}x2−dy2=k与r2−ds2=1相乘得到(x2−dy2)(r2−ds2)=(xr±dys)2−d(xs±yr)2=k)\mathbf{(x^2-dy^2)(r^2-ds^2)=(xr\pm dys)^2-d(xs\pm yr)^2=k)}(x2−dy2)(r2−ds2)=(xr±dys)2−d(xs±yr)2=k),于是得到关于一般的佩尔型方程的通解为xn=xn−1r±dyn−1s,yn=xn−1s±yn−1r\mathbf{x_n=x_{n-1}r\pm dy_{n-1}s,y_n=x_{n-1}s\pm y_{n-1}r}xn​=xn−1​r±dyn−1​s,yn​=xn−1​s±yn−1​r。

这里提供一个解任意佩尔型方程的在线网站:佩尔型方程在线求解

(3).求解方法

这里以标准的佩尔方程x2−dy2=1,d>1为非平方数\mathbf{x^2-dy^2=1,d>1为非平方数}x2−dy2=1,d>1为非平方数为例给出两种求解的方法。这两种方法都能够求出佩尔方程的一个最小特解,利用这个最小特解我们能够迅速找到方程的所有解。方法是构造二次域结构体然后快速幂计算即可,不过一般直接for循环递推也行,因为解的增长速度非常快。

[1].暴力法

由于x=1+dy2\mathbf{x=\sqrt{1+dy^2}}x=1+dy2​,我们考虑从1开始枚举y\mathbf{y}y,然后计算出x=⌊1+dy2⌋\mathbf{x=\lfloor \sqrt{1+dy^2} \rfloor}x=⌊1+dy2​⌋,然后判断是否满足佩尔方程即可,直到找到第一个解,这一定是最小解。
代码如下:

pi pell(ll d){//计算关于x^2-dy^2=1的一个最小正整数解 ll gd=(ll)sqrt(d);if(gd*gd==d)return mk(1,0);//判断d是否为平方数ll y=1,x;while(true){x=(ll)sqrtl(1+d*y*y);if(x*x-d*y*y==1)break;y++;}return mk(x,y);
}int main(){int t;rd(&t);while(t--){ll d;rd(&d);pi ans=pell(d);wrn(ans.fi,ans.se);}
}

[2].连分数法

<1>.连分数介绍

先介绍一下连分数,有限的连分数长这样子:a0+1a1+1a2+1⋱+1an\mathbf{a_0+\cfrac{1}{a_1+\cfrac{1}{a_2+\cfrac{1}{\ddots+\cfrac 1{a_n}}}}}a0​+a1​+a2​+⋱+an​1​1​1​1​,这样写太麻烦了,因此我们简记为AnBn=[a0,a1,...,an]\mathbf{\frac {A_n}{B_n}=[a_0,a_1,...,a_n]}Bn​An​​=[a0​,a1​,...,an​],现在我们看看AnBn\mathbf{\frac{A_n}{B_n}}Bn​An​​如何计算。
考虑从分数嵌套的最里层开始向外计算,设最里层有A0B0=an\mathbf{\frac {A_0}{B_0}=a_n}B0​A0​​=an​,于是有:
A1B1=an−1+1an=an−1+B0A0=A0an−1+B0A0⇒A1=A0an−1+B0,B1=A0\mathbf{\frac{A_1}{B_1}=a_{n-1}+\frac 1{a_n}=a_{n-1}+\frac {B_0}{A_0}=\frac{A_0a_{n-1}+B_0}{A_0}\Rightarrow A_1=A_0a_{n-1}+B_0,B_1=A_0}B1​A1​​=an−1​+an​1​=an−1​+A0​B0​​=A0​A0​an−1​+B0​​⇒A1​=A0​an−1​+B0​,B1​=A0​
A2B2=an−2+1A1B1=an−2+B1A1=A1an−2+B1A1⇒A2=A1an−2+B1,B2=A1\mathbf{\frac{A_2}{B_2}=a_{n-2}+\frac 1{\frac{A_1}{B_1}}=a_{n-2}+\frac {B_1}{A_1}=\frac{A_1a_{n-2}+B_1}{A_1}\Rightarrow A_2=A_1a_{n-2}+B_1,B_2=A_1}B2​A2​​=an−2​+B1​A1​​1​=an−2​+A1​B1​​=A1​A1​an−2​+B1​​⇒A2​=A1​an−2​+B1​,B2​=A1​

从上面容易看出关于Ak,Bk\mathbf{A_k,B_k}Ak​,Bk​的递推式:Ak=Ak−1an−k+Bk−1,Bk=Ak−1\mathbf{A_k=A_{k-1}a_{n-k}+B_{k-1},B_k=A_{k-1}}Ak​=Ak−1​an−k​+Bk−1​,Bk​=Ak−1​,初始条件为A0=an,B0=1\mathbf{A_0=a_n,B_0=1}A0​=an​,B0​=1,通过该递推式我们能够将有限的连分式转化为一个分数AnBn\mathbf{\frac{A_n}{B_n}}Bn​An​​。

现在再看一下无限的连分数,它长这样,a0+1a1+1a2+1⋱+1ak+1⋱\mathbf{a_0+\cfrac{1}{a_1+\cfrac{1}{a_2+\cfrac{1}{\ddots+\cfrac 1{a_k+\cfrac{1}{\ddots }}}}}}a0​+a1​+a2​+⋱+ak​+⋱1​1​1​1​1​,跟有限连分式区别在于它是无限的(废话 ),我们同样简记为[a0,a1,a2,...]\mathbf{[a_0,a_1,a_2,...]}[a0​,a1​,a2​,...]。
然后这个连分式有什么用呢?这里有一个定理:所有无限连分数都是无理数,并且所有无理数都可以用一种精确的方式表示成无限连分数。
知道了这一点我们就有办法用连分数表示出类似于3,22...\mathbf{\sqrt 3,\sqrt{22}...}3​,22​...这样的无理数了。
然后还有一种特殊的无限连分数,这类无限连分数的a0,a1,a2,...,ak,...\mathbf{a_0,a_1,a_2,...,a_k,...}a0​,a1​,a2​,...,ak​,...是会周期性重复的,然后可以证明的是每个非完全平方数的开根号并展开成连分数后就是这样一类连分数,即其a序列会发生周期性重复,且其最小循环节是以a1\mathbf{a_1}a1​为起点
由于其具有循环节,且从a1\mathbf{a_1}a1​开始发生循环,我们不妨将其连分数简记为[a0;<a1,a2,...,an>]\mathbf{[a_0;<a_1,a_2,...,a_n>]}[a0​;<a1​,a2​,...,an​>],其中a1,a2,..,an\mathbf{a_1,a_2,..,a_n}a1​,a2​,..,an​是它的最小循环节,周期为n\mathbf{n}n。

我们假设某个非完全平方数是d\mathbf{d}d,那么如何得到d\mathbf{\sqrt d}d​展开成连分数后的循环节长度呢?这里需要利用另一个可以被证明(对证明感兴趣的去网上搜)的性质:an=2a0且∀i∈[1,n−1],ai≠2a0\mathbf{a_n=2a_0且\forall i\in[1,n-1],a_i\ne 2a_0}an​=2a0​且∀i∈[1,n−1],ai​​=2a0​。利用这个性质,我们不断展开d\mathbf{\sqrt d}d​的连分数,直到遇到ak\mathbf{a_k}ak​满足ak=2a0\mathbf{a_k=2a_0}ak​=2a0​,那么说明k=n=循环节长度\mathbf{k=n=循环节长度}k=n=循环节长度。

<2>.应用连分数求解佩尔方程

以上就是连分数的基本内容,现在介绍如何用连分数法求解佩尔方程,这里只考虑d\mathbf{d}d为非平方数时对应的解。
首先是一个定理:设x2−dy2=1\mathbf{x^2-dy^2=1}x2−dy2=1,且d=[a0;<a1,a2,...,an>]\mathbf{\sqrt d=[a_0;<a_1,a_2,...,a_n>]}d​=[a0​;<a1​,a2​,...,an​>],记AB=[a0,a1,a2,...,an−1]\mathbf{\frac AB=[a_0,a_1,a_2,...,a_{n-1}]}BA​=[a0​,a1​,a2​,...,an−1​],那么当n\mathbf{n}n为偶数时方程最小正整数解为x1=A,y1=B\mathbf{x_1=A,y_1=B}x1​=A,y1​=B,当n\mathbf{n}n为奇数的时候方程的最小正整数解为x1=2A2+1,y1=2AB\mathbf{x_1=2A^2+1,y_1=2AB}x1​=2A2+1,y1​=2AB。
根据这个定理我们发现只需要明白 如何把d\mathbf{\sqrt d}d​展开为连分数 以及 如何把[a0,a1,...,an−1]\mathbf{[a_0,a_1,...,a_{n-1}]}[a0​,a1​,...,an−1​]写成分数AB\mathbf{\frac AB}BA​ 那么我们就可以求解任意佩尔方程了,对于第二个问题我们已经在前面连分式的介绍中提到了,这里只提出如何解决第一个问题。

首先容易得到a0=⌊d⌋\mathbf{a_0=\lfloor \sqrt d \rfloor}a0​=⌊d​⌋,于是有1a1+1a2+1⋱=d−a0\mathbf{\cfrac{1}{a_1+\cfrac{1}{a_2+\cfrac{1}{\ddots}}}=\sqrt d-a_0}a1​+a2​+⋱1​1​1​=d​−a0​,进一步有a1+1a2+1a3+1⋱=1d−a0=d+a0d−a02\mathbf{a_1+\cfrac{1}{a_2+\cfrac{1}{a_3+\cfrac{1}{\ddots}}}=\frac{1}{\sqrt d-a_0}=\frac{\sqrt d+a_0}{d-a_0^2}}a1​+a2​+a3​+⋱1​1​1​=d​−a0​1​=d−a02​d​+a0​​。
好像很难发现规律,那就给出一个定理吧:可以证明ak+1ak+1+1ak+1+1⋱=d+ckbk\mathbf{a_k+\cfrac{1}{a_{k+1}+\cfrac 1{a_{k+1}+\cfrac 1{\ddots}}}=\frac{\sqrt d+c_k}{b_k}}ak​+ak+1​+ak+1​+⋱1​1​1​=bk​d​+ck​​成立,其中ck,dk\mathbf{c_k,d_k}ck​,dk​均是整数。,现在的问题在于怎么求出ck,dk\mathbf{c_k,d_k}ck​,dk​。
显然ak=⌊d+ckbk⌋\mathbf{a_k=\lfloor \frac{\sqrt d+c_k}{b_k} \rfloor}ak​=⌊bk​d​+ck​​⌋,于是ak+1+1ak+2+1⋱=1d+ckbk−ak=bk(d+akbk−ck)d−(ck−akbk)2\mathbf{a_{k+1}+\cfrac1{a_{k+2}+\cfrac 1{\ddots}}=\cfrac{1}{\frac{\sqrt d+c_k}{b_k}-a_k}=\frac{b_k(\sqrt d+a_kb_k-c_k)}{d-(c_k-a_kb_k)^2}}ak+1​+ak+2​+⋱1​1​=bk​d​+ck​​−ak​1​=d−(ck​−ak​bk​)2bk​(d​+ak​bk​−ck​)​,其次还可以证明到bk∣(d−(ck−akbk)2)\mathbf{b_k\mid (d-(c_k-a_kb_k)^2)}bk​∣(d−(ck​−ak​bk​)2)成立,故ak+1+1ak+2+1⋱=d+akbk−ck[d−(ck−akbk)2]/bk\mathbf{a_{k+1}+\cfrac1{a_{k+2}+\cfrac 1{\ddots}}=\frac{\sqrt d+a_kb_k-c_k}{[d-(c_k-a_kb_k)^2]/b_k}}ak+1​+ak+2​+⋱1​1​=[d−(ck​−ak​bk​)2]/bk​d​+ak​bk​−ck​​,于是ak+1=⌊d+akbk−ck[d−(ck−akbk)2]/bk⌋\mathbf{a_{k+1}=\lfloor \frac{\sqrt d+a_kb_k-c_k}{[d-(c_k-a_kb_k)^2]/b_k} \rfloor}ak+1​=⌊[d−(ck​−ak​bk​)2]/bk​d​+ak​bk​−ck​​⌋,并且关于ck,bk\mathbf{c_k,b_k}ck​,bk​的递推式也可以得出,即ck+1=akbk−ck,bk+1=[d−(ck−akbk)2]bk\mathbf{c_{k+1}=a_kb_k-c_k,b_{k+1}=\frac {[d-(c_k-a_kb_k)^2]}{b_k}}ck+1​=ak​bk​−ck​,bk+1​=bk​[d−(ck​−ak​bk​)2]​,而它们的初始条件是a0=⌊d⌋,b0=1,c0=0\mathbf{a_0=\lfloor \sqrt d \rfloor,b_0=1,c_0=0}a0​=⌊d​⌋,b0​=1,c0​=0。

总结一下怎么求解佩尔方程,首先我们通过递推计算出关于d\mathbf{\sqrt d}d​的连分式中的an\mathbf{a_n}an​,计算的方式是利用递推式:a0=⌊d⌋,b0=1,c0=0,ak+1=⌊d+akbk−ck[d−(ck−akbk)2]/bk⌋,bk+1=[d−(ck−akbk)2]bk,ck+1=akbk−ck\mathbf{a_0=\lfloor \sqrt d \rfloor,b_0=1,c_0=0,a_{k+1}=\lfloor \frac{\sqrt d+a_kb_k-c_k}{[d-(c_k-a_kb_k)^2]/b_k} \rfloor,b_{k+1}=\frac {[d-(c_k-a_kb_k)^2]}{b_k},c_{k+1}=a_kb_k-c_k}a0​=⌊d​⌋,b0​=1,c0​=0,ak+1​=⌊[d−(ck​−ak​bk​)2]/bk​d​+ak​bk​−ck​​⌋,bk+1​=bk​[d−(ck​−ak​bk​)2]​,ck+1​=ak​bk​−ck​,直到满足ak=2a0\mathbf{a_k=2a_0}ak​=2a0​的时候我们说此时有k=n\mathbf{k=n}k=n并且循环节就是n\mathbf{n}n,然后我们对有限连分式[a0,a1,...,an−1]\mathbf{[a_0,a_1,...,a_{n-1}]}[a0​,a1​,...,an−1​]化简为An−1Bn−1\mathbf{\frac {A_{n-1}}{B_{n-1}}}Bn−1​An−1​​,化简方法是递推,递推关系满足A0=an−1,B0=1,Ak=Ak−1an−1−k+Bk−1,Bk=Ak−1\mathbf{A_0=a_{n-1},B_0=1,A_k=A_{k-1}a_{n-1-k}+B_{k-1},B_k=A_{k-1}}A0​=an−1​,B0​=1,Ak​=Ak−1​an−1−k​+Bk−1​,Bk​=Ak−1​。最后根据n\mathbf{n}n的奇偶性来判断解,当n\mathbf{n}n为奇数则最小正整数解为x1=2An−12+1,y1=2An−1Bn−1\mathbf{x_1=2A_{n-1}^2+1,y_1=2A_{n-1}B_{n-1}}x1​=2An−12​+1,y1​=2An−1​Bn−1​,当n\mathbf{n}n为偶数则最小正整数解为x1=An−1,y1=Bn−1\mathbf{x_1=A_{n-1},y_1=B_{n-1}}x1​=An−1​,y1​=Bn−1​。

注意我们上面所考虑的佩尔方程都是d为非完全平方数的情况。

下面给出一份参考代码:

ll a[maxn],b[maxn],c[maxn],A[maxn],B[maxn];
pi cal(ll *a,int n){//计算连分式[a0,a1,a2,...,an]的分数形式 A[n]=a[n],B[n]=1;ROF(i,n-1,0){A[i]=A[i+1]*a[i+1]+B[i+1];B[i]=A[i+1];}return mk(A[0],B[0]);
}
ll square(ll x){return x*x;
}
pi pell(ll d){ll gd=(ll)sqrtl(d);if(gd*gd==d)return mk(1,0);int n;a[0]=gd,b[0]=1,c[0]=0;n=1;while(true){a[n]=(ll)((gd+a[n-1]*b[n-1]-c[n-1])/((d-square(c[n-1]-a[n-1]*b[n-1]))/b[n-1]));b[n]=(d-square(c[n-1]-a[n-1]*b[n-1]))/b[n-1];c[n]=a[n-1]*b[n-1]-c[n-1];if(a[n]==2*a[0])break;n++;}pi ans=cal(a,n-1);if(n%2==0)return mk(ans.fi,ans.se);return mk(2*ans.fi*ans.fi+1,2*ans.fi*ans.se);
} int main(){int t;rd(&t);while(t--){ll d;rd(&d);pi ans=pell(d);wrn(ans.fi,ans.se);}
}

由于佩尔方程的解特别大,故这再给出一份java的代码:

import java.io.*;
import java.util.*;
import java.math.*;public class test {public static BigInteger add(BigInteger a,BigInteger b) {return a.add(b);}public static BigInteger sub(BigInteger a,BigInteger b) {return a.subtract(b);}public static BigInteger mul(BigInteger a,BigInteger b) {return a.multiply(b);}public static BigInteger squr(BigInteger a) {return a.multiply(a);}public static BigInteger div(BigInteger a,BigInteger b) {return a.divide(b);}public static long sqrtl(long x) {return (long)java.lang.Math.sqrt((double)x);}public static class Node{public BigInteger x,y;public Node(){x = BigInteger.valueOf(0);y = BigInteger.valueOf(0);}}public static Node mk(BigInteger x,BigInteger y) {Node ans= new Node();ans.x = x;ans.y = y;return ans;}public static BigInteger Big(long x) {return BigInteger.valueOf(x);}public static int maxn = 1000;public static BigInteger []A = new BigInteger [maxn];public static BigInteger []B = new BigInteger [maxn];public static BigInteger []a = new BigInteger [maxn];public static BigInteger []b = new BigInteger [maxn];public static BigInteger []c = new BigInteger [maxn];public static Node cal(BigInteger []a,int n) {A[n] = a[n];B[n] = BigInteger.valueOf(1);for(int i = n-1; i >= 0; --i) {A[i] = add(mul(A[i+1],a[i]),B[i+1]);B[i] = A[i+1];}return mk(A[0],B[0]);}public static Node pell(long d) {BigInteger dd = Big(d);Node ans = new Node();BigInteger gd = BigInteger.valueOf(sqrtl(d));if(mul(gd,gd).equals(dd))return mk(Big(1),Big(0));int n = 1;a[0] = gd;b[0] = Big(1);c[0] = Big(0);BigInteger a20 = mul(Big(2),a[0]);while(true) {c[n] = sub(mul(a[n-1],b[n-1]),c[n-1]);b[n] = div(sub(dd,squr(sub(c[n-1],mul(a[n-1],b[n-1])))),b[n-1]);a[n] = div(add(gd,c[n]),b[n]);if(a[n].equals(a20))break;n++;}ans = cal(a,n-1);if(n%2==0)return mk(ans.x,ans.y);return mk(add(mul(Big(2),squr(ans.x)),Big(1)),mul(Big(2),mul(ans.x,ans.y)));}public static void main(String args[]) {Scanner cin = new Scanner(System.in);int t = cin.nextInt();while((t--) > 0) {long d;d = cin.nextLong();Node ans = pell(d);System.out.println(ans.x+" "+ans.y);}}
}

(4).习题

这里提供四道习题,主要是熟悉佩尔方程的套路公式,不过没有找到需要用到连分式法的题目,事实上一般你只要会暴力就可以解决大部分题目了…但还是建议尽量掌握连分式法,它能够计算的数据范围十分惊人,即使是几百位的解也只需要不到一秒就可以进行求解。
例题一
题目来源:HDUHeron and His Triangle

题面:

题解:考虑海伦公式S=p(p−a)(p−b)(p−c),a=a+b+c2\mathbf{S=\sqrt{p(p-a)(p-b)(p-c)},a=\frac{a+b+c}{2}}S=p(p−a)(p−b)(p−c)​,a=2a+b+c​,我们将a=t−1,b=t,c=t+1\mathbf{a=t-1,b=t,c=t+1}a=t−1,b=t,c=t+1代入公式并化解可以得到S=3(t2)2((t2)2−1)\mathbf{S=\sqrt{3{(\frac t2)}^2({(\frac t2)}^2-1)}}S=3(2t​)2((2t​)2−1)​,要想S\mathbf{S}S是一个整数则必须满足t2\mathbf{\frac t2}2t​是一个整数(如果t为奇数显然S不会为整数),不妨设x=2t\mathbf{x=2t}x=2t,于是要满足3(x2−1)\mathbf{3(x^2-1)}3(x2−1)是一个平方数,即x2−1=3k2\mathbf{x^2-1=3k^2}x2−1=3k2存在整数解,移项可以得到x2−3k2=1\mathbf{x^2-3k^2=1}x2−3k2=1,这是一个典型的佩尔方程,肉眼可以看出它的一个最小解为x1=2,k1=1\mathbf{x_1=2,k_1=1}x1​=2,k1​=1(这样就不需要用连分数法了),于是利用公式(xnkn)\mathbf{\begin{pmatrix}x_n\\k_n\end{pmatrix}}(xn​kn​​)=(x13k1k1x1)⋅(xn−1kn−1)\mathbf{\begin{pmatrix}x_1&3k_1\\ k_1 & x_1\end{pmatrix}\cdot \begin{pmatrix}x_{n-1}\\k_{n-1}\end{pmatrix}}(x1​k1​​3k1​x1​​)⋅(xn−1​kn−1​​)进行递推即可,如果感觉矩阵不方便可以拆成两个式子来看,即xn=x1xn−1+3k1kn−1,kn=k1xn−1+x1kn−1\mathbf{x_n=x_1x_{n-1}+3k_1k_{n-1},k_n=k_1x_{n-1}+x_1k_{n-1}}xn​=x1​xn−1​+3k1​kn−1​,kn​=k1​xn−1​+x1​kn−1​。注意到这个式子递推的增速是指数级别的,会非常快,递推个一百项数字的位数可以高达近六十位,故我们暴力预处理即可,查询的时候也不用二分,暴力遍历找即可。
由于数据范围很大,这里给出java版的大数代码:

代码:

import java.io.*;
import java.util.*;
import java.math.*;public class Main {public static BigInteger mul(BigInteger a,BigInteger b) {return a.multiply(b);}public static BigInteger add(BigInteger a,BigInteger b) {return a.add(b);}public static BigInteger sub(BigInteger a,BigInteger b) {return a.subtract(b);}public static void main(String args[]) {BigInteger []t = new BigInteger[500];BigInteger []k = new BigInteger[500];final int maxn = 100;t[0] = BigInteger.valueOf(2);k[0] = BigInteger.valueOf(1);for(int i = 1;i < maxn; ++i) {k[i] = add(mul(t[i-1],k[0]),mul(t[0],k[i-1]));t[i] = add(mul(t[0],t[i-1]),mul(BigInteger.valueOf(3),mul(k[0],k[i-1])));}for(int i = 0;i < maxn; ++i) {t[i] = mul(BigInteger.valueOf(2),t[i]);}int T;Scanner cin = new Scanner(System.in);T = cin.nextInt();while((T--)>0) {BigInteger n = new BigInteger(cin.next());for(int i = 0;i < maxn; ++i) {if(t[i].compareTo(n) >= 0) {System.out.println(t[i]);break;}}}}
}

例题二
题目来源:POJStreet Numbers

题面:

题解:本题题意就是让求一个序列1,2,3,...,n,...,m\mathbf{1,2,3,...,n,...,m}1,2,3,...,n,...,m满足1+2+...+(n−1)=(n+1)+(n+2)+...+m\mathbf{1+2+...+(n-1)=(n+1)+(n+2)+...+m}1+2+...+(n−1)=(n+1)+(n+2)+...+m,我们化解一下式子并且配方可以得到一个方程(2m+1)2−8n2=1\mathbf{{(2m+1)}^2-8n^2=1}(2m+1)2−8n2=1,这个方程是个典型的佩尔方程,只需要令x=2m+1,y=n\mathbf{x=2m+1,y=n}x=2m+1,y=n我们就能得到其标准形式x2−8y2=1\mathbf{x^2-8y^2=1}x2−8y2=1,显然最小解为x=3,y=1\mathbf{x=3,y=1}x=3,y=1,然后就是套路的递推式了:xn=x1xn−1+8y1yn−1,yn=y1xn−1+x1yn−1\mathbf{x_n=x_1x_{n-1}+8y_1y_{n-1},y_n=y_1x_{n-1}+x_1y_{n-1}}xn​=x1​xn−1​+8y1​yn−1​,yn​=y1​xn−1​+x1​yn−1​。本题的难点在于想到配方成一个佩尔方程。

代码:

int main(){ll x[20],y[20];x[0]=3,y[0]=1;FOR(i,1,11){x[i]=x[i-1]*x[0]+8ll*y[i-1]*y[0];y[i]=y[0]*x[i-1]+x[0]*y[i-1];}FOR(i,1,11){printf("%10lld%10lld\n",y[i],(x[i]-1)/2);}
}

例题三
题目来源:HDUNo more tricks, Mr Nanguo

题面:

题解:题意就是给你n,k\mathbf{n,k}n,k,让你找第k\mathbf{k}k小的x\mathbf{x}x满足x2−ny2=1\mathbf{x^2-ny^2=1}x2−ny2=1,注意到当n\mathbf{n}n是完全平方数的时候方程只有一个正解x=1,y=0\mathbf{x=1,y=0}x=1,y=0,故此时若k=1\mathbf{k=1}k=1输出1即可,否则输出无解。但是当n\mathbf{n}n不是完全平方数的时候我们由于这个方程是佩尔方程故一定有解,这里的n\mathbf{n}n很小,因此我们可以暴力求出它的最小解,然后根据公式xn+ynd=(x1+y1d)n\mathbf{x_n+y_n\sqrt d=(x_1+y_1\sqrt d)^n}xn​+yn​d​=(x1​+y1​d​)n用扩展二次域快速幂直接求解即可。
代码:

const ll mod = 8191;
ll x[30],y[30];
pi pell(ll d){ll x,y=1;while(true){x=(ll)sqrtl(d*y*y+1);if(x*x-d*y*y==1)return mk(x,y);y++;}
}
void init(int n){FOR(i,1,n+1){ll ii=(ll)sqrtl(i);if(ii*ii==i)continue;pi ans=pell(i);x[i]=ans.fi,y[i]=ans.se;}
}
ll d;
struct Node{ll x,y;Node(ll x=1,ll y=0):x(x),y(y){}
};
Node operator*(Node a,Node b){return Node((a.x*b.x%mod+d*a.y*b.y%mod)%mod,(a.x*b.y%mod+a.y*b.x%mod)%mod);
}
Node qpow(Node a,ll b){Node ans;while(b){if(b&1)ans=ans*a;a=a*a;b>>=1;}return ans;
}
int main(){init(28);ll n,k;while(~scanf("%lld%lld",&n,&k)){ll nn=(ll)sqrtl(n);if(nn*nn==n){if(k==1)wrn(1);else wrn("No answers can meet such conditions");continue;}Node a = Node(x[n],y[n]);d = n;a = qpow(a,k);wrn(a.x);}
}

例题四
题目来源:HDUSquare Number

题面:

题解:首先列出方程配方,然后得到式子(4n+3)2−48x2=1\mathbf{(4n+3)^2-48x^2=1}(4n+3)2−48x2=1,我们令X=4n+3,Y=x\mathbf{X=4n+3,Y=x}X=4n+3,Y=x,于是有佩尔方程X2−48Y2=1\mathbf{X^2-48Y^2=1}X2−48Y2=1,容易得到一个最小解为X1=7,Y1=1\mathbf{X_1=7,Y_1=1}X1​=7,Y1​=1,然后就是常规的递推式Xn=X1Xn−1+48Y1Yn−1,Yn=X1Yn−1+Y1Xn−1\mathbf{X_n=X_1X_{n-1}+48Y_1Y_{n-1},Y_n=X_1Y_{n-1}+Y_1X_{n-1}}Xn​=X1​Xn−1​+48Y1​Yn−1​,Yn​=X1​Yn−1​+Y1​Xn−1​,注意到到不是所有的X,Y\mathbf{X,Y}X,Y都是合法的,还要满足n=X−34\mathbf{n=\frac{X-3}4}n=4X−3​是一个整数才是合法解,所以小于1e18\mathbf{1e18}1e18的解很少,其实只有8个,直接预处理后在询问的时候暴力查找再输出即可。

代码:

ll x[maxn+1],y[maxn+1],ansn[maxn+1],ansx[maxn+1];
int main(){x[0]=7,y[0]=1;FOR(i,1,maxn){x[i]=x[i-1]*x[0]+48*y[i-1]*y[0];y[i]=y[0]*x[i-1]+x[0]*y[i-1];}int tot=0;FOR(i,0,maxn){if((x[i]-3)%4==0){ansn[tot]=(x[i]-3)/4,ansx[tot]=y[i];tot++;}}ansn[tot]=INF;ll n;while(~scanf("%lld",&n) && n){FOR(i,0,tot+1)if(ansn[i]>n){wrn(ansn[i-1],ansx[i-1]);break;}}
}

4.类欧几里得算法

(1).定义

设f(a,b,c,n)=∑i=0n⌊ai+bc⌋,h(a,b,c,n)=∑i=0n⌊ai+bc⌋2,g(a,b,c,n)=∑i=0ni⌊ai+bc⌋\mathbf{f(a,b,c,n)=\sum_{i=0}^n\lfloor {ai+b\over c}\rfloor,h(a,b,c,n)=\sum_{i=0}^n\lfloor {ai+b\over c}\rfloor^2,g(a,b,c,n)=\sum_{i=0}^ni\lfloor{ai+b\over c}\rfloor}f(a,b,c,n)=∑i=0n​⌊cai+b​⌋,h(a,b,c,n)=∑i=0n​⌊cai+b​⌋2,g(a,b,c,n)=∑i=0n​i⌊cai+b​⌋,类欧几里得算法主要是通过形式类似欧几里得算法的递归来求解以上三个式子(当然还有些由此扩展出来的式子)。

(2).f函数求解

先从最简单的f(a,b,c,n)=∑i=0n⌊ai+bc⌋\mathbf{f(a,b,c,n)=\sum_{i=0}^n\lfloor {ai+b\over c}\rfloor}f(a,b,c,n)=∑i=0n​⌊cai+b​⌋入手,分两种情况。
1.若a≥c或b≥c\mathbf{a\ge c 或 b\ge c}a≥c或b≥c,则f(a,b,c,n)=∑i=0n⌊ai+bc⌋=∑i=0n⌊⌊ac⌋i+⌊bc⌋+⌊(a%c)i+(b%c)c⌋⌋=∑i=0n⌊ac⌋i+∑i=0n⌊bc⌋+∑i=0n⌊(a%c)i+(b%c)c⌋=⌊ac⌋n(n+1)2+⌊bc⌋(n+1)+f(a%c,b%c,c,n)\mathbf{\begin{aligned}f(a,b,c,n) &=\sum_{i=0}^n\lfloor {ai+b\over c}\rfloor \\ &=\sum_{i=0}^n\lfloor\lfloor{a\over c} \rfloor i+\lfloor {b\over c}\rfloor+\lfloor{(a\%c)i+(b\%c)\over c}\rfloor \rfloor\\ &=\sum_{i=0}^n\lfloor{a\over c} \rfloor i+\sum_{i=0}^n\lfloor{b\over c}\rfloor+\sum_{i=0}^n\lfloor{(a\%c)i+(b\%c)\over c}\rfloor\\ &=\lfloor{a\over c}\rfloor{n(n+1)\over 2}+\lfloor{b\over c}\rfloor(n+1)+f(a\%c,b\%c,c,n) \end{aligned}}f(a,b,c,n)​=i=0∑n​⌊cai+b​⌋=i=0∑n​⌊⌊ca​⌋i+⌊cb​⌋+⌊c(a%c)i+(b%c)​⌋⌋=i=0∑n​⌊ca​⌋i+i=0∑n​⌊cb​⌋+i=0∑n​⌊c(a%c)i+(b%c)​⌋=⌊ca​⌋2n(n+1)​+⌊cb​⌋(n+1)+f(a%c,b%c,c,n)​
于是情况1就变成了情况2,因为a%c<a,b%c<b\mathbf{a\%c<a,b\%c<b}a%c<a,b%c<b。
2.若a<c且b<c\mathbf{a<c且b<c}a<c且b<c,则f(a,b,c,n)=∑i=0n⌊ai+bc⌋=∑i=0n∑j=1⌊an+bc⌋[j≤⌊ai+bc⌋]=∑i=0n∑j=1⌊an+bc⌋[jc≤ai+b]=∑i=0n∑j=1⌊an+bc⌋[jc−b−1<ai]=∑i=0n∑j=1⌊an+bc⌋[i>⌊jc−b−1a⌋]=∑j=0⌊an+bc⌋−1∑i=0n[i>⌊jc+c−b−1a⌋]=∑j=0⌊an+bc⌋−1(n−⌊jc+c−b−1a⌋)=n⌊an+bc⌋−∑i=0⌊an+bc⌋−1⌊ci+c−b−1a⌋=n⌊an+bc⌋−f(c,c−b−1,a,⌊an+bc⌋−1)\mathbf{\begin{aligned}f(a,b,c,n) &=\sum_{i=0}^n\lfloor {ai+b\over c}\rfloor \\ &=\sum_{i=0}^n\sum_{j=1}^{\lfloor {an+b\over c}\rfloor}[j\le \lfloor {ai+b\over c}\rfloor] \\ &=\sum_{i=0}^n\sum_{j=1}^{\lfloor {an+b\over c}\rfloor}[jc\le ai+b] \\ &=\sum_{i=0}^n\sum_{j=1}^{\lfloor {an+b\over c}\rfloor}[jc-b-1< ai] \\ &=\sum_{i=0}^n\sum_{j=1}^{\lfloor {an+b\over c}\rfloor}[i>\lfloor{jc-b-1\over a}\rfloor] \\ &=\sum_{j=0}^{\lfloor {an+b\over c}\rfloor-1}\sum_{i=0}^n[i>\lfloor{jc+c-b-1\over a}\rfloor] \\ &=\sum_{j=0}^{\lfloor {an+b\over c}\rfloor-1}(n-\lfloor{jc+c-b-1\over a}\rfloor) \\ &=n\lfloor {an+b\over c}\rfloor-\sum_{i=0}^{\lfloor {an+b\over c}\rfloor-1}\lfloor{ci+c-b-1\over a}\rfloor \\ &=n\lfloor {an+b\over c}\rfloor-f(c,c-b-1,a,\lfloor {an+b\over c}\rfloor-1) \\ \end{aligned}}f(a,b,c,n)​=i=0∑n​⌊cai+b​⌋=i=0∑n​j=1∑⌊can+b​⌋​[j≤⌊cai+b​⌋]=i=0∑n​j=1∑⌊can+b​⌋​[jc≤ai+b]=i=0∑n​j=1∑⌊can+b​⌋​[jc−b−1<ai]=i=0∑n​j=1∑⌊can+b​⌋​[i>⌊ajc−b−1​⌋]=j=0∑⌊can+b​⌋−1​i=0∑n​[i>⌊ajc+c−b−1​⌋]=j=0∑⌊can+b​⌋−1​(n−⌊ajc+c−b−1​⌋)=n⌊can+b​⌋−i=0∑⌊can+b​⌋−1​⌊aci+c−b−1​⌋=n⌊can+b​⌋−f(c,c−b−1,a,⌊can+b​⌋−1)​
方便起见,我们设m=⌊an+bc⌋\mathbf{m=\lfloor {an+b\over c}\rfloor}m=⌊can+b​⌋,于是有f(a,b,c,n)=mn−f(c,c−b−1,a,m−1)\mathbf{f(a,b,c,n)=mn-f(c,c-b-1,a,m-1)}f(a,b,c,n)=mn−f(c,c−b−1,a,m−1),然后就可以递归下去求出f\mathbf{f}f了,递归的边界有两个,当n=0\mathbf{n=0}n=0时,返回⌊bc⌋\mathbf{\lfloor {b\over c}\rfloor}⌊cb​⌋即可;当a=0\mathbf{a=0}a=0时返回⌊bc⌋(n+1)\mathbf{\lfloor {b\over c}\rfloor(n+1)}⌊cb​⌋(n+1)即可。
代码也非常好些,这里给出一份参考代码(未取模版本):

ll sm1(ll n){return (n*(n+1)%mod*inv2%mod);}
ll sm2(ll n){return (n*(n+1)%mod*(2*n+1)%mod*inv6%mod);}
ll sqr(ll x){return x*x%mod;}
ll f(ll a,ll b,ll c,ll n){if(!a)return b/c*(n+1);if(!n)return b/c;ll ac=a/c,bc=b/c,m=(a*n+b)/c;if(a>=c || b>=c)return ac*sm1(n)+bc*(n+1)+f(a%c,b%c,c,n);return m*n-f(c,c-b-1,a,m-1);
}

(3).h函数求解

类似于f\mathbf{f}f函数我们对h\mathbf{h}h函数作以下推导,注意式子中会出现对f\mathbf{f}f函数和g\mathbf{g}g函数的调用。
仍然先分情况。
1.若a≥c或b≥c\mathbf{a\ge c 或 b\ge c}a≥c或b≥c,则有
h(a,b,c,n)=∑i=0n⌊ai+bc⌋2=∑i=0n(⌊ac⌋i+⌊bc⌋+⌊(a%c)i+(b%c)c⌋)2=∑i=0n⌊ac⌋2i2+∑i=0n⌊bc⌋2+∑i=0n⌊(a%c)i+(b%c)c⌋2+∑i=0n2⌊ac⌋⌊bc⌋i+∑i=0n2⌊bc⌋⌊(a%c)i+(b%c)c⌋+∑i=0n2⌊ac⌋⌊(a%c)i+(b%c)c⌋i=⌊ac⌋2n(n+1)(2n+1)6+2⌊ac⌋⌊bc⌋n(n+1)2+⌊bc⌋2(n+1)+h(a%c,b%c,c,n)+2⌊bc⌋f(a%c,b%c,c,n)+2⌊ac⌋g(a%c,b%c,c,n)\mathbf{\begin{aligned} h(a,b,c,n)&=\sum_{i=0}^n\lfloor{ai+b\over c}\rfloor^2\\ &=\sum_{i=0}^n(\lfloor{a\over c} \rfloor i+\lfloor {b\over c}\rfloor+\lfloor{(a\%c)i+(b\%c)\over c}\rfloor)^2\\ &=\sum_{i=0}^n\lfloor{a\over c}\rfloor^2i^2+\sum_{i=0}^n\lfloor{b\over c}\rfloor^2+\sum_{i=0}^n\lfloor{(a\%c)i+(b\%c)\over c}\rfloor^2+\sum_{i=0}^n2\lfloor{a\over c}\rfloor\lfloor{b\over c}\rfloor i+\sum_{i=0}^n2\lfloor{b\over c}\rfloor\lfloor{(a\%c)i+(b\%c)\over c}\rfloor+\sum_{i=0}^n2\lfloor{a\over c}\rfloor\lfloor{(a\%c)i+(b\%c)\over c}\rfloor i\\ &=\lfloor{a\over c}\rfloor^2{n(n+1)(2n+1)\over 6}+2\lfloor{a\over c}\rfloor\lfloor{b\over c}\rfloor {n(n+1)\over 2}+\lfloor{b\over c}\rfloor^2(n+1)+h(a\%c,b\%c,c,n)+2\lfloor{b\over c}\rfloor f(a\%c,b\%c,c,n)+2\lfloor{a\over c}\rfloor g(a\%c,b\%c,c,n) \end{aligned}}h(a,b,c,n)​=i=0∑n​⌊cai+b​⌋2=i=0∑n​(⌊ca​⌋i+⌊cb​⌋+⌊c(a%c)i+(b%c)​⌋)2=i=0∑n​⌊ca​⌋2i2+i=0∑n​⌊cb​⌋2+i=0∑n​⌊c(a%c)i+(b%c)​⌋2+i=0∑n​2⌊ca​⌋⌊cb​⌋i+i=0∑n​2⌊cb​⌋⌊c(a%c)i+(b%c)​⌋+i=0∑n​2⌊ca​⌋⌊c(a%c)i+(b%c)​⌋i=⌊ca​⌋26n(n+1)(2n+1)​+2⌊ca​⌋⌊cb​⌋2n(n+1)​+⌊cb​⌋2(n+1)+h(a%c,b%c,c,n)+2⌊cb​⌋f(a%c,b%c,c,n)+2⌊ca​⌋g(a%c,b%c,c,n)​
2.若a<c且b<c\mathbf{a<c 且 b< c}a<c且b<c,我们还是令则有
h(a,b,c,n)=∑i=0n⌊ai+bc⌋2=∑i=0n∑j=1⌊an+bc⌋[j≤⌊ai+bc⌋]∑k=1⌊an+bc⌋[k≤⌊ai+bc⌋=∑i=0n∑j=1⌊an+bc⌋[cj≤ai+b]∑k=1⌊an+bc⌋[ck≤ai+b]=∑i=0n∑j=0⌊an+bc⌋−1[cj+c−b−1<ai]∑k=0⌊an+bc⌋−1[ck+c−b−1<ai]=∑i=0n∑j=0⌊an+bc⌋−1[i>⌊cj+c−b−1a⌋]∑k=0⌊an+bc⌋−1[i>⌊ck+c−b−1a⌋]=∑j=0⌊an+bc⌋−1∑k=0⌊an+bc⌋−1∑i=0n[i>⌊cj+c−b−1a⌋][i>⌊ck+c−b−1a⌋]=∑j=0⌊an+bc⌋−1∑k=0⌊an+bc⌋−1∑i=0n[i>max{⌊cj+c−b−1a⌋,⌊ck+c−b−1a⌋}]=∑j=0⌊an+bc⌋−1∑k=0⌊an+bc⌋−1(n−max{⌊cj+c−b−1a⌋,⌊ck+c−b−1a⌋})\mathbf{\begin{aligned} h(a,b,c,n)&=\sum_{i=0}^n\lfloor{ai+b\over c}\rfloor^2\\ &=\sum_{i=0}^n\sum_{j=1}^{\lfloor{an+b\over c}\rfloor}[j\le \lfloor{ai+b\over c}\rfloor]\sum_{k=1}^{\lfloor{an+b\over c}\rfloor}[k\le \lfloor{ai+b\over c}\rfloor\\ &=\sum_{i=0}^n\sum_{j=1}^{\lfloor{an+b\over c}\rfloor}[cj\le ai+b]\sum_{k=1}^{\lfloor{an+b\over c}\rfloor}[ck\le ai+b]\\ &=\sum_{i=0}^n\sum_{j=0}^{\lfloor{an+b\over c}\rfloor-1}[cj+c-b-1<ai]\sum_{k=0}^{\lfloor{an+b\over c}\rfloor-1}[ck+c-b-1<ai]\\ &=\sum_{i=0}^n\sum_{j=0}^{\lfloor{an+b\over c}\rfloor-1}[i>\lfloor {cj+c-b-1\over a}\rfloor]\sum_{k=0}^{\lfloor{an+b\over c}\rfloor-1}[i>\lfloor {ck+c-b-1\over a}\rfloor]\\ &=\sum_{j=0}^{\lfloor{an+b\over c}\rfloor-1}\sum_{k=0}^{\lfloor{an+b\over c}\rfloor-1}\sum_{i=0}^n[i>\lfloor {cj+c-b-1\over a}\rfloor][i>\lfloor {ck+c-b-1\over a}\rfloor]\\ &=\sum_{j=0}^{\lfloor{an+b\over c}\rfloor-1}\sum_{k=0}^{\lfloor{an+b\over c}\rfloor-1}\sum_{i=0}^n[i>max\{\lfloor {cj+c-b-1\over a}\rfloor,\lfloor {ck+c-b-1\over a}\rfloor\}]\\ &=\sum_{j=0}^{\lfloor{an+b\over c}\rfloor-1}\sum_{k=0}^{\lfloor{an+b\over c}\rfloor-1}(n-max\{\lfloor {cj+c-b-1\over a}\rfloor,\lfloor {ck+c-b-1\over a}\rfloor\})\\ \end{aligned}}h(a,b,c,n)​=i=0∑n​⌊cai+b​⌋2=i=0∑n​j=1∑⌊can+b​⌋​[j≤⌊cai+b​⌋]k=1∑⌊can+b​⌋​[k≤⌊cai+b​⌋=i=0∑n​j=1∑⌊can+b​⌋​[cj≤ai+b]k=1∑⌊can+b​⌋​[ck≤ai+b]=i=0∑n​j=0∑⌊can+b​⌋−1​[cj+c−b−1<ai]k=0∑⌊can+b​⌋−1​[ck+c−b−1<ai]=i=0∑n​j=0∑⌊can+b​⌋−1​[i>⌊acj+c−b−1​⌋]k=0∑⌊can+b​⌋−1​[i>⌊ack+c−b−1​⌋]=j=0∑⌊can+b​⌋−1​k=0∑⌊can+b​⌋−1​i=0∑n​[i>⌊acj+c−b−1​⌋][i>⌊ack+c−b−1​⌋]=j=0∑⌊can+b​⌋−1​k=0∑⌊can+b​⌋−1​i=0∑n​[i>max{⌊acj+c−b−1​⌋,⌊ack+c−b−1​⌋}]=j=0∑⌊can+b​⌋−1​k=0∑⌊can+b​⌋−1​(n−max{⌊acj+c−b−1​⌋,⌊ack+c−b−1​⌋})​
现在这个max\mathbf{max}max似乎很棘手,我们分情况考虑就能避免max\mathbf{max}max了。
若⌊cj+c−b−1a⌋>⌊ck+c−b−1a⌋\mathbf{\lfloor {cj+c-b-1\over a}\rfloor>\lfloor {ck+c-b-1\over a}\rfloor}⌊acj+c−b−1​⌋>⌊ack+c−b−1​⌋,这时候的和sum1=∑j=0⌊an+bc⌋−1j(n−⌊cj+c−b−1a⌋)=n∑j=0⌊an+bc⌋−1j−∑j=0⌊an+bc⌋−1j⌊cj+c−b−1a⌋=n⌊an+bc⌋(⌊an+bc⌋−1)2−g(c,c−b−1,a,⌊an+bc⌋−1)\mathbf{sum_1=\sum_{j=0}^{\lfloor{an+b\over c}\rfloor-1}j(n-\lfloor {cj+c-b-1\over a}\rfloor)=n\sum_{j=0}^{\lfloor{an+b\over c}\rfloor-1}j-\sum_{j=0}^{\lfloor{an+b\over c}\rfloor-1}j\lfloor {cj+c-b-1\over a}\rfloor=n{\lfloor{an+b\over c}\rfloor(\lfloor{an+b\over c}\rfloor-1)\over 2}-g(c,c-b-1,a,\lfloor{an+b\over c}\rfloor-1)}sum1​=∑j=0⌊can+b​⌋−1​j(n−⌊acj+c−b−1​⌋)=n∑j=0⌊can+b​⌋−1​j−∑j=0⌊can+b​⌋−1​j⌊acj+c−b−1​⌋=n2⌊can+b​⌋(⌊can+b​⌋−1)​−g(c,c−b−1,a,⌊can+b​⌋−1);
若⌊cj+c−b−1a⌋<⌊ck+c−b−1a⌋\mathbf{\lfloor {cj+c-b-1\over a}\rfloor<\lfloor {ck+c-b-1\over a}\rfloor}⌊acj+c−b−1​⌋<⌊ack+c−b−1​⌋,根据对称性有则sum2=sum1\mathbf{sum_2=sum_1}sum2​=sum1​;
若⌊cj+c−b−1a⌋=⌊ck+c−b−1a⌋\mathbf{\lfloor {cj+c-b-1\over a}\rfloor=\lfloor {ck+c-b-1\over a}\rfloor}⌊acj+c−b−1​⌋=⌊ack+c−b−1​⌋,则sum3=∑i=0⌊an+bc⌋−1(n−⌊ci+c−b−1a⌋)=n⌊an+bc⌋−f(c,c−b−1,a,⌊an+bc⌋−1)\mathbf{sum_3=\sum_{i=0}^{\lfloor{an+b\over c}\rfloor-1}(n-\lfloor {ci+c-b-1\over a}\rfloor)=n\lfloor{an+b\over c}\rfloor -f(c,c-b-1,a,\lfloor{an+b\over c}\rfloor-1)}sum3​=∑i=0⌊can+b​⌋−1​(n−⌊aci+c−b−1​⌋)=n⌊can+b​⌋−f(c,c−b−1,a,⌊can+b​⌋−1)。
综上h(a,b,c,n)=sum1+sum2+sum3=n⌊an+bc⌋2−2g(c,c−b−1,a,⌊an+bc⌋−1)−f(c,c−b−1,a,⌊an+bc⌋−1)\mathbf{h(a,b,c,n)=sum_1+sum_2+sum_3=n\lfloor{an+b\over c}\rfloor^2-2g(c,c-b-1,a,\lfloor{an+b\over c}\rfloor-1)-f(c,c-b-1,a,\lfloor{an+b\over c}\rfloor-1)}h(a,b,c,n)=sum1​+sum2​+sum3​=n⌊can+b​⌋2−2g(c,c−b−1,a,⌊can+b​⌋−1)−f(c,c−b−1,a,⌊can+b​⌋−1)
令m=⌊an+bc⌋\mathbf{m=\lfloor{an+b\over c}\rfloor}m=⌊can+b​⌋则可以简化式子为h(a,b,c,n)=nm2−2g(c,c−b−1,a,m−1)−f(c,c−b−1,a,m−1)\mathbf{h(a,b,c,n)=nm^2-2g(c,c-b-1,a,m-1)-f(c,c-b-1,a,m-1)}h(a,b,c,n)=nm2−2g(c,c−b−1,a,m−1)−f(c,c−b−1,a,m−1)。

h\mathbf{h}h函数的递归边界与f\mathbf{f}f相似,第一种是n=0\mathbf{n=0}n=0的时候,我们返回⌊bc⌋2\mathbf{\lfloor {b\over c}\rfloor^2}⌊cb​⌋2即可;第二种是a=0\mathbf{a=0}a=0的时候,我们返回⌊bc⌋2(n+1)\mathbf{\lfloor {b\over c}\rfloor^2(n+1)}⌊cb​⌋2(n+1)即可。
下面给出一份参考代码(未取模版本):

ll sm1(ll n){return (n*(n+1)%mod*inv2%mod);}
ll sm2(ll n){return (n*(n+1)%mod*(2*n+1)%mod*inv6%mod);}
ll sqr(ll x){return x*x%mod;}
ll h(ll a,ll b,ll c,ll n){if(!a)return sqr(b/c)*(n+1);if(!n)return sqr(b/c);ll ac=a/c,bc=b/c,m=(a*n+b)/c;if(a>=c || b>=c)return sqr(ac)*sm2(n)+2*ac*bc*sm1(n)+sqr(bc)*(n+1)+h(a%c,b%c,c,n)+2*bc*f(a%c,b%c,c,n)+2*ac*g(a%c,b%c,c,n);return n*sqr(m)-2*g(c,c-b-1,a,m-1)-f(c,c-b-1,a,m-1);
}

(4).g函数求解

还是套路式地推式子即可。
1.若a≥c或b≥c\mathbf{a\ge c 或b\ge c}a≥c或b≥c,则有
g(a,b,c,n)=∑i=0ni⌊ai+bc⌋=∑i=0ni(⌊ac⌋i+⌊bc⌋+⌊(a%c)i+(b%c)c⌋)=∑i=0n(⌊ac⌋i2+⌊bc⌋i+⌊(a%c)i+(b%c)c⌋i)=⌊ac⌋n(n+1)(2n+1)6+⌊bc⌋n(n+1)2+∑i=0n⌊(a%c)i+(b%c)c⌋i=⌊ac⌋n(n+1)(2n+1)6+⌊bc⌋n(n+1)2+g(a%c,b%c,c,n)\mathbf{\begin{aligned} g(a,b,c,n)&=\sum_{i=0}^ni\lfloor{ai+b\over c}\rfloor\\ &=\sum_{i=0}^ni(\lfloor {a\over c}\rfloor i+\lfloor {b\over c}\rfloor +\lfloor{(a\%c)i+(b\%c)\over c}\rfloor)\\ &=\sum_{i=0}^n(\lfloor {a\over c}\rfloor i^2+\lfloor {b\over c}\rfloor i +\lfloor{(a\%c)i+(b\%c)\over c}\rfloor i)\\ &=\lfloor {a\over c}\rfloor {n(n+1)(2n+1)\over 6}+\lfloor {b\over c}\rfloor {n(n+1)\over 2}+\sum_{i=0}^n\lfloor{(a\%c)i+(b\%c)\over c}\rfloor i\\ &=\lfloor {a\over c}\rfloor {n(n+1)(2n+1)\over 6}+\lfloor {b\over c}\rfloor {n(n+1)\over 2}+g(a\%c,b\%c,c,n)\\ \end{aligned}}g(a,b,c,n)​=i=0∑n​i⌊cai+b​⌋=i=0∑n​i(⌊ca​⌋i+⌊cb​⌋+⌊c(a%c)i+(b%c)​⌋)=i=0∑n​(⌊ca​⌋i2+⌊cb​⌋i+⌊c(a%c)i+(b%c)​⌋i)=⌊ca​⌋6n(n+1)(2n+1)​+⌊cb​⌋2n(n+1)​+i=0∑n​⌊c(a%c)i+(b%c)​⌋i=⌊ca​⌋6n(n+1)(2n+1)​+⌊cb​⌋2n(n+1)​+g(a%c,b%c,c,n)​

2.若a<c且b<c\mathbf{a<c且b<c}a<c且b<c,则有
g(a,b,c,n)=∑i=0ni⌊ai+bc⌋=∑i=0ni∑j=1⌊ai+bc⌋[j≤⌊ai+bc⌋]=∑i=0ni∑j=1⌊ai+bc⌋[i>⌊jc−b−1a⌋]=∑j=0⌊ai+bc⌋−1∑i=0ni[i>⌊jc+c−b−1a⌋]=∑j=0⌊ai+bc⌋−1∑i=⌊jc+c−b−1a⌋+1ni=∑j=0⌊ai+bc⌋−1(⌊jc+c−b−1a⌋+1+n)(n−⌊jc+c−b−1a⌋)2=12∑j=0⌊ai+bc⌋−1(n(n+1)−⌊jc+c−b−1a⌋−⌊jc+c−b−1a⌋2)=12(n(n+1)⌊ai+bc⌋−f(c,c−b−1,a,⌊ai+bc⌋−1)−h(c,c−b−1,a,⌊ai+bc⌋−1))\mathbf{\begin{aligned} g(a,b,c,n)&=\sum_{i=0}^ni\lfloor{ai+b\over c}\rfloor\\ &=\sum_{i=0}^ni\sum_{j=1}^{\lfloor{ai+b\over c}\rfloor}[j\le \lfloor{ai+b\over c}\rfloor]\\ &=\sum_{i=0}^ni\sum_{j=1}^{\lfloor{ai+b\over c}\rfloor}[i>\lfloor{jc-b-1\over a}\rfloor]\\ &=\sum_{j=0}^{\lfloor{ai+b\over c}\rfloor-1}\sum_{i=0}^ni[i>\lfloor{jc+c-b-1\over a}\rfloor]\\ &=\sum_{j=0}^{\lfloor{ai+b\over c}\rfloor-1}\sum_{i=\lfloor{jc+c-b-1\over a}\rfloor+1}^ni\\ &=\sum_{j=0}^{\lfloor{ai+b\over c}\rfloor-1}{(\lfloor{jc+c-b-1\over a}\rfloor+1+n)(n-\lfloor{jc+c-b-1\over a}\rfloor)\over 2}\\ &=\frac 12\sum_{j=0}^{\lfloor{ai+b\over c}\rfloor-1}(n(n+1)-\lfloor{jc+c-b-1\over a}\rfloor-\lfloor{jc+c-b-1\over a}\rfloor^2)\\ &=\frac 12(n(n+1)\lfloor{ai+b\over c}\rfloor-f(c,c-b-1,a,\lfloor{ai+b\over c}\rfloor-1)-h(c,c-b-1,a,\lfloor{ai+b\over c}\rfloor-1))\\ \end{aligned}}g(a,b,c,n)​=i=0∑n​i⌊cai+b​⌋=i=0∑n​ij=1∑⌊cai+b​⌋​[j≤⌊cai+b​⌋]=i=0∑n​ij=1∑⌊cai+b​⌋​[i>⌊ajc−b−1​⌋]=j=0∑⌊cai+b​⌋−1​i=0∑n​i[i>⌊ajc+c−b−1​⌋]=j=0∑⌊cai+b​⌋−1​i=⌊ajc+c−b−1​⌋+1∑n​i=j=0∑⌊cai+b​⌋−1​2(⌊ajc+c−b−1​⌋+1+n)(n−⌊ajc+c−b−1​⌋)​=21​j=0∑⌊cai+b​⌋−1​(n(n+1)−⌊ajc+c−b−1​⌋−⌊ajc+c−b−1​⌋2)=21​(n(n+1)⌊cai+b​⌋−f(c,c−b−1,a,⌊cai+b​⌋−1)−h(c,c−b−1,a,⌊cai+b​⌋−1))​
令m=⌊ai+bc⌋\mathbf{m=\lfloor{ai+b\over c}\rfloor}m=⌊cai+b​⌋于是g(a,b,c,n)=12(n(n+1)m−f(c,c−b−1,a,m−1)−h(c,c−b−1,a,m−1)\mathbf{g(a,b,c,n)=\frac 12(n(n+1)m-f(c,c-b-1,a,m-1)-h(c,c-b-1,a,m-1)}g(a,b,c,n)=21​(n(n+1)m−f(c,c−b−1,a,m−1)−h(c,c−b−1,a,m−1)。

边界条件满足当n=0\mathbf{n=0}n=0时返回0\mathbf{0}0,当a=0\mathbf{a=0}a=0时返回⌊bc⌋n(n+1)2\mathbf{\lfloor{b\over c}\rfloor{n(n+1)\over 2}}⌊cb​⌋2n(n+1)​。
这里给出一份参考代码(未取模版本):

ll sm1(ll n){return (n*(n+1)%mod*inv2%mod);}
ll sm2(ll n){return (n*(n+1)%mod*(2*n+1)%mod*inv6%mod);}
ll sqr(ll x){return x*x%mod;}
ll g(ll a,ll b,ll c,ll n){if(!a)return (b/c)*sm1(n);if(!n)return 0;ll ac=a/c,bc=b/c,m=(a*n+b)/c;if(a>=c || b>=c)return ac*sm2(n)+bc*sm1(n)+g(a%c,b%c,c,n);return (n*(n+1)*m-f(c,c-b-1,a,m-1)-h(c,c-b-1,a,m-1))/2;
}

(5).模板总结

这里给出一个取模的模板。

const ll mod = 998244353;
ll inv3 = qpow(3,mod-2,mod),inv2 = qpow(2,mod-2,mod),inv6=qpow(6,mod-2,mod);
ll f(ll a,ll b,ll c,ll n);
ll h(ll a,ll b,ll c,ll n);
ll g(ll a,ll b,ll c,ll n);
ll sm1(ll n){return (n*(n+1)%mod*inv2%mod);}
ll sm2(ll n){return (n*(n+1)%mod*(2*n+1)%mod*inv6%mod);}
ll sqr(ll x){return x*x%mod;}
ll f(ll a,ll b,ll c,ll n){if(!a)return (b/c)*(n+1)%mod;if(!n)return b/c%mod;ll ac=a/c,bc=b/c,m=(a*n+b)/c;if(a>=c || b>=c)return (ac*sm1(n)%mod+bc*(n+1)%mod+f(a%c,b%c,c,n))%mod;return ((m%mod*n%mod-f(c,c-b-1,a,m-1))%mod+mod)%mod;
}
ll h(ll a,ll b,ll c,ll n){if(!a)return sqr(b/c)*(n+1)%mod;if(!n)return sqr(b/c);ll ac=(a/c)%mod,bc=(b/c)%mod,m=(a*n+b)/c,mm=m%mod;if(a>=c || b>=c)return (sqr(ac)*sm2(n)%mod+2*ac*bc%mod*sm1(n)%mod+sqr(bc)*(n+1)%mod+h(a%c,b%c,c,n)+2*bc*f(a%c,b%c,c,n)%mod+2*ac*g(a%c,b%c,c,n)%mod)%mod;return ((n*sqr(mm)%mod-2*g(c,c-b-1,a,m-1)-f(c,c-b-1,a,m-1))%mod+mod)%mod;
}
ll g(ll a,ll b,ll c,ll n){if(!a)return (b/c)*sm1(n)%mod;if(!n)return 0;ll ac=a/c%mod,bc=b/c%mod,m=(a*n+b)/c,mm=m%mod;if(a>=c || b>=c)return (ac*sm2(n)%mod+bc*sm1(n)%mod+g(a%c,b%c,c,n))%mod;return ((n*(n+1)%mod*mm%mod-f(c,c-b-1,a,m-1)-h(c,c-b-1,a,m-1))%mod*inv2%mod+mod)%mod;
}

(6).习题

例题一
题目来源:LuoGuP5170 【模板】类欧几里得算法

题面:

题解:本题要求同时求出f,g,h\mathbf{f,g,h}f,g,h,注意到这些函数在递归过程中会互相调用,并且存在许多相同的调用,如果我们单独求出每个函数显然很不合算,复杂度也会比较高,于是考虑将三个函数合成一个函数,这样就可以同时共用一个调用的值。
代码:

const ll mod = 998244353;
ll inv3 = qpow(3,mod-2,mod),inv2 = qpow(2,mod-2,mod),inv6=qpow(6,mod-2,mod);
ll sm1(ll n){return (n*(n+1)%mod*inv2%mod);}
ll sm2(ll n){return (n*(n+1)%mod*(2*n+1)%mod*inv6%mod);}
ll sqr(ll x){return x*x%mod;}
ll f(ll a,ll b,ll c,ll n){if(!a)return (b/c)*(n+1)%mod;if(!n)return b/c%mod;ll ac=a/c,bc=b/c,m=(a*n+b)/c;if(a>=c || b>=c)return (ac*sm1(n)%mod+bc*(n+1)%mod+f(a%c,b%c,c,n))%mod;return ((m%mod*n%mod-f(c,c-b-1,a,m-1))%mod+mod)%mod;
}
ll g(ll a,ll b,ll c,ll n){if(!a)return (b/c)*sm1(n)%mod;if(!n)return 0;ll ac=a/c%mod,bc=b/c%mod,m=(a*n+b)/c,mm=m%mod;if(a>=c || b>=c)return (ac*sm2(n)%mod+bc*sm1(n)%mod+g(a%c,b%c,c,n))%mod;return ((n*(n+1)%mod*mm%mod-f(c,c-b-1,a,m-1)-h(c,c-b-1,a,m-1))%mod*inv2%mod+mod)%mod;
}
ll h(ll a,ll b,ll c,ll n){if(!a)return sqr(b/c)*(n+1)%mod;if(!n)return sqr(b/c);ll ac=(a/c)%mod,bc=(b/c)%mod,m=(a*n+b)/c,mm=m%mod;if(a>=c || b>=c)return (sqr(ac)*sm2(n)%mod+2*ac*bc%mod*sm1(n)%mod+sqr(bc)*(n+1)%mod+h(a%c,b%c,c,n)+2*bc*f(a%c,b%c,c,n)%mod+2*ac*g(a%c,b%c,c,n)%mod)%mod;return ((n*sqr(mm)%mod-2*g(c,c-b-1,a,m-1)-f(c,c-b-1,a,m-1))%mod+mod)%mod;
}struct Node{ll f,g,h;Node(ll f=0,ll g=0,ll h=0):f(f),g(g),h(h){}
};Node cal(ll a,ll b,ll c,ll n){Node ans;ll ac=a/c,bc=b/c,m=(a*n+b)/c,mm=m%mod;if(!a)ans=Node(bc*(n+1)%mod,bc*sm1(n)%mod,sqr(bc)*(n+1)%mod);else if(!n)ans=Node(bc%mod,0,sqr(bc));else if(a>=c || b>=c){Node as=cal(a%c,b%c,c,n);ans=Node((ac*sm1(n)%mod+bc*(n+1)%mod+as.f)%mod,(ac*sm2(n)%mod+bc*sm1(n)%mod+as.g)%mod,(sqr(ac)*sm2(n)%mod+2*ac*bc%mod*sm1(n)%mod+sqr(bc)*(n+1)%mod+as.h+2*bc*as.f%mod+2*ac*as.g%mod)%mod);}else{Node as=cal(c,c-b-1,a,m-1);ans=Node((m%mod*n%mod-as.f)%mod,(n*(n+1)%mod*mm%mod-as.f-as.h)%mod*inv2%mod,(n*sqr(mm)%mod-2*as.g-as.f)%mod);}return ans;
}
int main(){int t;rd(&t);while(t--){ll n,a,b,c;rd(&n,&a,&b,&c);Node ans=cal(a,b,c,n);wrn((ans.f+mod)%mod,(ans.h+mod)%mod,(ans.g+mod)%mod);}
}

例题二
题目来源:CFCF1182FMaximum Sine

题面:

题解:我们注意到∣sin(x)∣\mathbf{|sin(x)|}∣sin(x)∣是一个周期为π\mathbf{\pi}π的函数,我们可以让px\mathbf{px}px对q\mathbf{q}q取模,于是能够得到∣sin((px)%qqπ)∣\mathbf{|sin(\frac{(px)\%q}q\pi )|}∣sin(q(px)%q​π)∣,现在能保证(px)%qqπ∈[0,π)\mathbf{\frac{(px)\%q}q\pi \in[0,\pi)}q(px)%q​π∈[0,π)了,那么要让函数值最大,则要求∣(px)%qq−12∣\mathbf{|\frac{(px)\%q}q-\frac 12|}∣q(px)%q​−21​∣尽可能小,即∣(2px)%(2q)−q∣\mathbf{|(2px)\%(2q)-q|}∣(2px)%(2q)−q∣尽可能小。
然后是思维的转化,我们考虑这个式子的值能否等于0,能否等于1,能否等于2…显然这样做效率很低且不具有单调性,我们不妨考虑(2px)%(2q)\mathbf{(2px)\%(2q)}(2px)%(2q)能否属于[q,q]\mathbf{[q,q]}[q,q],能否属于[q−1,q+1]\mathbf{[q-1,q+1]}[q−1,q+1],能否属于…,我们发现当(2px)%(2q)\mathbf{(2px)\%(2q)}(2px)%(2q)属于一个小范围的时候,一定能够属于一个大范围,具有单调性,于是可以考虑二分这个范围。那么怎么判断(2px)%(2q)\mathbf{(2px)\%(2q)}(2px)%(2q)能否属于[l,r]\mathbf{[l,r]}[l,r]这个范围呢?一个非常神奇的技巧是当这个式子存在解使得它的值位于[l,r]\mathbf{[l,r]}[l,r]的时候,一定有∃x0,⌊2px0−l2q⌋>⌊2px0−r−12q⌋\mathbf{\exist x_0,\lfloor \frac{2px_0-l}{2q}\rfloor>\lfloor \frac{2px_0-r-1}{2q}\rfloor}∃x0​,⌊2q2px0​−l​⌋>⌊2q2px0​−r−1​⌋成立,因此也一定有∑x=ab(⌊2px0−l2q⌋−⌊2px0−r−12q⌋)>0\mathbf{\sum_{x=a}^{b}(\lfloor \frac{2px_0-l}{2q}\rfloor-\lfloor \frac{2px_0-r-1}{2q}\rfloor)>0}∑x=ab​(⌊2q2px0​−l​⌋−⌊2q2px0​−r−1​⌋)>0成立。这一步变换需要好好领悟,有了这个式子剩下的工作就很简单了,一看就是一个类欧的标准范式,套模板算出它的解即可。
二分出范围[q−d,q+d]\mathbf{[q-d,q+d]}[q−d,q+d]后,由于这是最小范围,故一定有(2px)%(2q)=q−d或q+d\mathbf{(2px)\%(2q)=q-d或q+d}(2px)%(2q)=q−d或q+d成立,对两个都做一遍扩欧求同余方程即可,然后由于要求解范围在[a,b]\mathbf{[a,b]}[a,b]之间,根据通解公式能够算出一个最小解,然后两个最小解取最小的一个即可。
代码:

ll sm(ll n){return n*(n+1)/2;}
ll sqr(ll n){return n*n;}
int sgn(ll n){return (n<0?-1:1);}
ll f(ll a,ll b,ll c,ll n){if(!a)return b/c*(n+1);if(!n)return b/c;if(a>=c || b>=c)return a/c*sm(n)+b/c*(n+1)+f(a%c,b%c,c,n);ll m=(a*n+b)/c;return n*m-f(c,c-b-1,a,m-1);
}
ll a,b,p,q;
bool check(ll l,ll r){ll sm1=a?f(2*p,2*q-l,2*q,b)-f(2*p,2*q-l,2*q,a-1):f(2*p,2*q-l,2*q,b);ll sm2=a?f(2*p,2*q-r-1,2*q,b)-f(2*p,2*q-r-1,2*q,a-1):f(2*p,2*q-r-1,2*q,b);if(sm1-sm2>0)return true;return false;
}
ll cel(ll a,ll b){if(a%b==0)return a/b;if(sgn(a)*sgn(b)<0)return a/b;return a/b+1;
}
ll exgcd(ll a,ll b,ll &x,ll &y){ll ans;if(!b)ans=a,x=1,y=0;else ans=exgcd(b,a%b,y,x),y-=a/b*x;return ans;
}
int main(){int t;rd(&t);while(t--){rd(&a,&b,&p,&q);ll l=0,r=q,d=-1,ans;while(l<=r){ll mid=l+r>>1;if(check(q-mid,q+mid)){r=mid-1;d=mid;}else{l=mid+1;}}ll res=q-d,x,y,ans1=INF,ans2=INF;ll dd=exgcd(2*p,2*q,x,y);if(res%dd==0){ans1=x*res/dd;ans1+=cel(a-ans1,2*q/(dd))*(2*q/(dd));if(ans1>b)ans1=INF;}res=q+d;if(res%dd==0){ans2=x*res/dd;ans2+=cel(a-ans2,2*q/(dd))*(2*q/dd);if(ans2>b)ans2=INF;} ans=min(ans1,ans2);wrn(ans);}
}

例题三
题目来源:LOJ#138. 类欧几里得算法

题面:

题解:需要多项式,暂鸽,学了多项式来补。。。

十、数论函数

1.整除分块

(1).引理

  1. ⌊abc⌋=⌊⌊ab⌋c⌋\mathbf{\lfloor \frac a{bc}\rfloor=\lfloor \frac{\lfloor \frac ab\rfloor}{c}\rfloor}⌊bca​⌋=⌊c⌊ba​⌋​⌋。
    证明:设a=kbc+r,r<bc\mathbf{a=kbc+r,r<bc}a=kbc+r,r<bc,则有⌊abc⌋=k\mathbf{\lfloor \frac{a}{bc}\rfloor = k}⌊bca​⌋=k,⌊⌊ab⌋c⌋=⌊⌊kbc+rb⌋c⌋=⌊kc+⌊rb⌋c⌋=⌊k+⌊rb⌋c⌋=k+⌊⌊rb⌋c⌋\mathbf{\lfloor \frac{\lfloor \frac ab\rfloor}{c}\rfloor=\lfloor \frac{\lfloor \frac {kbc+r}b\rfloor}{c}\rfloor=\lfloor \frac{kc+\lfloor \frac rb\rfloor}{c}\rfloor=\lfloor k+\frac{\lfloor \frac rb\rfloor}{c}\rfloor=k+\lfloor \frac{\lfloor \frac rb\rfloor}{c}\rfloor}⌊c⌊ba​⌋​⌋=⌊c⌊bkbc+r​⌋​⌋=⌊ckc+⌊br​⌋​⌋=⌊k+c⌊br​⌋​⌋=k+⌊c⌊br​⌋​⌋,又因为r<bc\mathbf{r<bc}r<bc,故⌊rb⌋<c\mathbf{\lfloor \frac rb \rfloor<c}⌊br​⌋<c,进而有⌊⌊rb⌋c⌋=0\mathbf{\lfloor \frac{\lfloor \frac rb\rfloor}{c}\rfloor=0}⌊c⌊br​⌋​⌋=0,即⌊⌊ab⌋c⌋=k=⌊abc⌋\mathbf{\lfloor \frac{\lfloor \frac ab\rfloor}{c}\rfloor=k=\lfloor \frac a{bc}\rfloor}⌊c⌊ba​⌋​⌋=k=⌊bca​⌋。
  2. ⌊nd⌋\mathbf{\lfloor \frac nd\rfloor}⌊dn​⌋的取值只有约⌊2n⌋\mathbf{\lfloor2\sqrt n\rfloor}⌊2n​⌋种。
    证明:这里给出一个简略的证法,当d<⌊n⌋\mathbf{d<\lfloor \sqrt n\rfloor}d<⌊n​⌋时⌊nd⌋\mathbf{\lfloor \frac nd\rfloor}⌊dn​⌋最多有⌊n⌋\mathbf{\lfloor \sqrt n\rfloor}⌊n​⌋种取值,当d≥⌊n⌋\mathbf{d\ge \lfloor \sqrt n \rfloor}d≥⌊n​⌋时由于⌊nd⌋≤⌊n⌋\mathbf{\lfloor \frac nd \rfloor\le \lfloor \sqrt n\rfloor}⌊dn​⌋≤⌊n​⌋故⌊nd⌋\mathbf{\lfloor \frac nd\rfloor}⌊dn​⌋最多有⌊n⌋\mathbf{\lfloor \sqrt n\rfloor}⌊n​⌋种取值,综上⌊nd⌋\mathbf{\lfloor \frac nd\rfloor}⌊dn​⌋最多有2⌊n⌋\mathbf{2\lfloor \sqrt n\rfloor}2⌊n​⌋种取值。
  3. 若a≤b\mathbf{a\le b}a≤b,则⌊a⌋≤⌊b⌋\mathbf{\lfloor a\rfloor \le \lfloor b\rfloor}⌊a⌋≤⌊b⌋。
    证明:显然正确。

(2).分块

考虑对于任意一个i≤n,i∈Z+,n∈Z+\mathbf{i\le n,i\in Z^+,n\in Z^+}i≤n,i∈Z+,n∈Z+而言,我们找到一个最大的j\mathbf{j}j满足⌊ni⌋=⌊nj⌋\mathbf{\lfloor \frac ni\rfloor =\lfloor \frac nj\rfloor}⌊in​⌋=⌊jn​⌋,那么j\mathbf{j}j如何求解呢?
假设⌊ni⌋=k\mathbf{\lfloor \frac ni\rfloor =k}⌊in​⌋=k,则有⌊nj⌋=k⇒k≤nj<k+1⇒nk+1<j≤nk\mathbf{\lfloor \frac nj\rfloor =k\Rightarrow k\le \frac nj<k+1\Rightarrow \frac n{k+1}<j\le \frac nk}⌊jn​⌋=k⇒k≤jn​<k+1⇒k+1n​<j≤kn​,根据引理3我们直接对式子下取整得到j=⌊j⌋≤⌊nk⌋,(注意j是整数,故j=⌊j⌋)\mathbf{j=\lfloor j\rfloor \le \lfloor \frac nk\rfloor,(注意j是整数,故j=\lfloor j\rfloor)}j=⌊j⌋≤⌊kn​⌋,(注意j是整数,故j=⌊j⌋),因此有max{j}=⌊nk⌋=⌊n⌊ni⌋⌋\mathbf{max\{j\}=\lfloor \frac nk\rfloor=\lfloor \frac n{\lfloor \frac ni\rfloor}\rfloor}max{j}=⌊kn​⌋=⌊⌊in​⌋n​⌋。
利用这个性质我们可以对一些运算进行分块处理,以最经典的一个求和式为例,我们求解⌊n1⌋+⌊n2⌋+⌊n3⌋+...+⌊nn⌋\mathbf{\lfloor \frac n1\rfloor+\lfloor \frac n2\rfloor+\lfloor \frac n3\rfloor+...+\lfloor\frac nn\rfloor}⌊1n​⌋+⌊2n​⌋+⌊3n​⌋+...+⌊nn​⌋的值,由于其中有很多项的值都是相同的,故我们可以把式子分成许多块,对应不同的i,j\mathbf{i,j}i,j,又根据引理2,⌊nd⌋\mathbf{\lfloor \frac nd\rfloor}⌊dn​⌋取值不超过O(n)\mathbf{O(\sqrt n)}O(n​),故我们实际上只会分出O(n)\mathbf{O(\sqrt n)}O(n​)块来,算法复杂度也是O(n)\mathbf{O(\sqrt n)}O(n​)。

2.积性函数

(1).定义

设f(1)=1\mathbf{f(1)=1}f(1)=1,若f(x)\mathbf{f(x)}f(x)满足对于任意正整数a,b\mathbf{a,b}a,b满足若gcd(a,b)=1\mathbf{gcd(a,b)=1}gcd(a,b)=1则有f(a)f(b)=f(ab)\mathbf{f(a)f(b)=f(ab)}f(a)f(b)=f(ab),则f(x)\mathbf{f(x)}f(x)是一个积性函数。
特别地,如果不要求gcd(a,b)=1\mathbf{gcd(a,b)=1}gcd(a,b)=1仍然满足f(a)f(b)=f(ab)\mathbf{f(a)f(b)=f(ab)}f(a)f(b)=f(ab),则将f(x)\mathbf{f(x)}f(x)称为完全积性函数。

(2).性质

  1. 若f(x),g(x)\mathbf{f(x),g(x)}f(x),g(x)为积性函数,则f(xk),fk(x),f(x)g(x),∑d∣xf(xd)g(d)(狄利克雷卷积)\mathbf{f(x^k),f^k(x),f(x)g(x),\sum_{d\mid x}f(\frac xd)g(d)(狄利克雷卷积)}f(xk),fk(x),f(x)g(x),∑d∣x​f(dx​)g(d)(狄利克雷卷积)均是积性函数。
    证明:首先已知f(x),g(x)\mathbf{f(x),g(x)}f(x),g(x)是积性函数,现在对这五个式子分别证明。
    f(xk):\mathbf{f(x^k):}f(xk):显然对于任意gcd(ak,bk)=1\mathbf{gcd(a^k,b^k)=1}gcd(ak,bk)=1一定有gcd(a,b)=1\mathbf{gcd(a,b)=1}gcd(a,b)=1,故f(ak)f(bk)=f(akbk)=f((ab)k)\mathbf{f(a^k)f(b^k)=f(a^kb^k)=f((ab)^k)}f(ak)f(bk)=f(akbk)=f((ab)k)。

    fk(x):\mathbf{f^k(x):}fk(x):设gcd(a,b)=1\mathbf{gcd(a,b)=1}gcd(a,b)=1,则有fk(a)fk(b)=f(a)f(b)f(a)f(b)...f(a)f(b),有k对f(a)f(b)=f(ab)f(ab)...f(ab)=fk(ab)\mathbf{f^k(a)f^k(b)=f(a)f(b)f(a)f(b)...f(a)f(b),有k对f(a)f(b)=f(ab)f(ab)...f(ab)=f^k(ab)}fk(a)fk(b)=f(a)f(b)f(a)f(b)...f(a)f(b),有k对f(a)f(b)=f(ab)f(ab)...f(ab)=fk(ab),故fk(x)\mathbf{f^k(x)}fk(x)是积性函数。

    f(x)g(x):\mathbf{f(x)g(x):}f(x)g(x):设gcd(a,b)=1\mathbf{gcd(a,b)=1}gcd(a,b)=1,则有f(a)g(a)f(b)g(b)=f(a)f(b)g(a)g(b)=f(ab)g(ab)\mathbf{f(a)g(a)f(b)g(b)=f(a)f(b)g(a)g(b)=f(ab)g(ab)}f(a)g(a)f(b)g(b)=f(a)f(b)g(a)g(b)=f(ab)g(ab),故是f(x)g(x)\mathbf{f(x)g(x)}f(x)g(x)是积性函数。

    ∑d∣xf(xd)g(d):\mathbf{\sum_{d\mid x}f(\frac xd)g(d):}∑d∣x​f(dx​)g(d):设gcd(a,b)=1\mathbf{gcd(a,b)=1}gcd(a,b)=1,则有∑d∣af(ad)g(d)∑d∣bf(bd)g(d)=∑d1∣a,d2∣bf(ad1)g(d1)f(bd2)g(d2)\mathbf{\sum_{d\mid a}f(\frac ad)g(d)\sum_{d\mid b}f(\frac bd)g(d)=\sum_{d_1\mid a,d_2\mid b}f(\frac a{d_1})g(d_1)f(\frac b{d_2})g(d_2)}∑d∣a​f(da​)g(d)∑d∣b​f(db​)g(d)=∑d1​∣a,d2​∣b​f(d1​a​)g(d1​)f(d2​b​)g(d2​),容易知道gcd(ad1,bd2)=1且gcd(d1,d2)=1\mathbf{gcd(\frac a{d_1},\frac b{d_2})=1且gcd(d_1,d_2)=1}gcd(d1​a​,d2​b​)=1且gcd(d1​,d2​)=1,于是有∑d1∣a,d2∣bf(ad1)g(d1)f(bd2)g(d2)=∑(d1d2)∣abf(abd1d2)g(d1d2)=∑d∣abf(abd)g(d)\mathbf{\sum_{d_1\mid a,d_2\mid b}f(\frac a{d_1})g(d_1)f(\frac b{d_2})g(d_2)=\sum_{(d_1d_2)\mid ab}f(\frac{ab}{d_1d_2})g(d_1d_2)=\sum_{d\mid ab}f(\frac {ab}d)g(d)}∑d1​∣a,d2​∣b​f(d1​a​)g(d1​)f(d2​b​)g(d2​)=∑(d1​d2​)∣ab​f(d1​d2​ab​)g(d1​d2​)=∑d∣ab​f(dab​)g(d),故f与g的狄利克雷卷积也是积性函数。

  2. 设x=p1a1p2a2...pkak\mathbf{p_1^{a_1}p_2^{a_2}...p_k^{a_k}}p1a1​​p2a2​​...pkak​​,若f(x)\mathbf{f(x)}f(x)是积性函数则有f(x)=∏i=1kf(piai)\mathbf{f(x)=\prod_{i=1}^kf(p_i^{a_i})}f(x)=∏i=1k​f(piai​​),特别地,若f(x)\mathbf{f(x)}f(x)是完全积性函数则有f(x)=∏i=1kf(pi)ai\mathbf{f(x)=\prod_{i=1}^kf(p_i)^{a_i}}f(x)=∏i=1k​f(pi​)ai​。
    证明:由积性函数的性质易证。

(3).常见积性函数

  1. 欧拉函数φ(n)\mathbf{\varphi(n)}φ(n)。
    证明:见第四部分5.(2)用5种提供了五种不同的方法证明欧拉函数是积性函数。
  2. 莫比乌斯函数μ(n)={1,if n=10,if∃d>1,d2∣n(−1)k,ifn=p1p2p3...pk,p是质数\mathbf{\mu(n)=\begin{cases}1,&\text{if }n=1\\0,&if \exist d>1,d^2\mid n\\ (-1)^k,& ifn=p_1p_2p_3...p_k,p是质数\end{cases}}μ(n)=⎩⎪⎨⎪⎧​1,0,(−1)k,​if n=1if∃d>1,d2∣nifn=p1​p2​p3​...pk​,p是质数​。
    证明:分类讨论一下即可。
    情况一a=1,b=1\mathbf{a=1,b=1}a=1,b=1:显然有μ(ab)=μ(a)μ(b)\mathbf{\mu(ab)=\mu(a)\mu(b)}μ(ab)=μ(a)μ(b)。
    情况二a=1,b=p1p2...pk\mathbf{a=1,b=p_1p_2...p_k}a=1,b=p1​p2​...pk​:于是有μ(ab)=μ(b)=μ(1)μ(b)=μ(a)μ(b)\mathbf{\mu(ab)=\mu(b)=\mu(1)\mu(b)=\mu(a)\mu(b)}μ(ab)=μ(b)=μ(1)μ(b)=μ(a)μ(b)。
    情况三a=p1p2...ps,b=p1p2...pt\mathbf{a=p_1p_2...p_s,b=p_1p_2...p_t}a=p1​p2​...ps​,b=p1​p2​...pt​:于是有μ(ab)=(−1)s+t=(−1)s(−1)t=μ(a)μ(b)\mathbf{\mu(ab)=(-1)^{s+t}=(-1)^s(-1)^t=\mu(a)\mu(b)}μ(ab)=(−1)s+t=(−1)s(−1)t=μ(a)μ(b)。
    情况四a和b中至少有一个有平方因子\mathbf{a和b中至少有一个有平方因子}a和b中至少有一个有平方因子:不妨设∃d>1,d2∣b\mathbf{\exist d>1,d^2\mid b}∃d>1,d2∣b,于是有μ(ab)=μ(0)=0=μ(0)μ(a)=μ(a)μ(b)\mathbf{\mu(ab)=\mu(0)=0=\mu(0)\mu(a)=\mu(a)\mu(b)}μ(ab)=μ(0)=0=μ(0)μ(a)=μ(a)μ(b)。
  3. σk(n)=∑d∣ndk\mathbf{\sigma_k(n)=\sum_{d\mid n}d^k}σk​(n)=∑d∣n​dk。
    证明:设gcd(a,b)=1\mathbf{gcd(a,b)=1}gcd(a,b)=1,则有σk(a)σk(b)=∑d1∣ad1k∑d2∣bd2k=∑d1∣a,d2∣bd1kd2k=∑d1d2∣ab(d1d2)k=∑d∣abdk=σk(ab)\mathbf{\sigma_k(a)\sigma_k(b)=\sum_{d_1\mid a}d_1^k\sum_{d_2 \mid b}d_2^k=\sum_{d_1\mid a,d_2\mid b}d_1^kd_2^k=\sum_{d_1d_2\mid ab}(d_1d_2)^k=\sum_{d\mid ab}d^k=\sigma_{k}(ab)}σk​(a)σk​(b)=∑d1​∣a​d1k​∑d2​∣b​d2k​=∑d1​∣a,d2​∣b​d1k​d2k​=∑d1​d2​∣ab​(d1​d2​)k=∑d∣ab​dk=σk​(ab)。
  4. 因数个数函数 d(n)=∑d∣n1\mathbf{d(n)=\sum_{d\mid n}1}d(n)=∑d∣n​1。
    证明:由于d(n)=σ0(n)\mathbf{d(n)=\sigma_0(n)}d(n)=σ0​(n),由3得证。
  5. 因数和函数σ(n)=∑d∣nd\mathbf{\sigma(n)=\sum_{d\mid n}d}σ(n)=∑d∣n​d
    证明:由于σ(n)=σ1(n)\mathbf{\sigma(n)=\sigma_1(n)}σ(n)=σ1​(n),由3得证。
  6. (完全积性)恒等函数I(n)=1\mathbf{I(n)=1}I(n)=1。
    证明:显然正确。
  7. (完全积性)单位元元函数ϵ(n)=[n=1]\mathbf{\epsilon(n)=[n=1]}ϵ(n)=[n=1]。
    证明:显然正确。
  8. (完全积性)单位函数id(n)=n\mathbf{id(n)=n}id(n)=n。
    证明:显然正确。

(4).线性筛预处理积性函数

线性筛预处理积性函数主要分三种情况(p表示n的最小质因数):

  1. n为质数的时候,此时我们直接能求出f(n)\mathbf{f(n)}f(n)。
  2. np%p=0\mathbf{\frac n{p}\%p=0}pn​%p=0的时候,此时要考虑f\mathbf{f}f函数的性质并根据f(n)\mathbf{f(n)}f(n)与f(np)\mathbf{f(\frac np)}f(pn​)的关系来求解f(n)\mathbf{f(n)}f(n)。
  3. np%p≠0\mathbf{\frac n{p}\%p\ne 0}pn​%p​=0的时候,仍然要考虑f\mathbf{f}f函数的性质然后求解f(n)\mathbf{f(n)}f(n)。

这三种情况对应着线性筛过程中的三个不同的分支,下面以几个常用积性函数为例进行讲解。

[1].莫比乌斯函数μ(n)\mathbf{\mu(n)}μ(n)

考虑莫比乌斯函数的表达式μ(n)={1,if n=10,if∃d>1,d2∣n(−1)k,ifn=p1p2p3...pk,p是质数\mathbf{\mu(n)=\begin{cases}1,&\text{if }n=1\\0,&if \exist d>1,d^2\mid n\\ (-1)^k,& ifn=p_1p_2p_3...p_k,p是质数\end{cases}}μ(n)=⎩⎪⎨⎪⎧​1,0,(−1)k,​if n=1if∃d>1,d2∣nifn=p1​p2​p3​...pk​,p是质数​。
根据表达式我们容易知道三种情况下对应的μ(n)\mathbf{\mu(n)}μ(n)值。

  1. 当n为质数,μ(n)=−1\mathbf{\mu(n)=-1}μ(n)=−1。
  2. 当np%p=0\mathbf{\frac np\%p=0}pn​%p=0,则μ(n)=0\mathbf{\mu(n)=0}μ(n)=0。
  3. 当np%p≠0\mathbf{\frac np\%p\ne 0}pn​%p​=0,则μ(n)=μ(np)μ(p)=−μ(np)\mathbf{\mu(n)=\mu(\frac np)\mu(p)=-\mu(\frac np)}μ(n)=μ(pn​)μ(p)=−μ(pn​)。

[2].约数个数函数d(n)\mathbf{d(n)}d(n)

设n=p1e1p2e2...pkek\mathbf{n=p_1^{e_1}p_2^{e_2}...p_k^{e_k}}n=p1e1​​p2e2​​...pkek​​。
在反素数那一节中我们讲到了d(n)=(e1+1)(e2+1)...(ek+1)\mathbf{d(n)=(e_1+1)(e_2+1)...(e_k+1)}d(n)=(e1​+1)(e2​+1)...(ek​+1),根据这个公式容易得到了d(n)\mathbf{d(n)}d(n)在三种情况下的式子。

  1. 当n为质数,d(n)=2\mathbf{d(n)=2}d(n)=2。
  2. 当np%p=0\mathbf{\frac np\%p=0}pn​%p=0,设e\mathbf{e}e表示np\mathbf{\frac np}pn​中的最小质数的指数,则d(n)=d(np)e+1e\mathbf{d(n)=d(\frac np)\frac{e+1}e}d(n)=d(pn​)ee+1​。
  3. 当np%p≠0\mathbf{\frac np\%p\ne 0}pn​%p​=0,则d(n)=2d(np)\mathbf{d(n)=2d(\frac np)}d(n)=2d(pn​)。

具体写代码的时候我们需要对每个数维护e\mathbf{e}e的值,这很容易做到,就不过多解释。

[3].约数和函数σ(n)\mathbf{\sigma(n)}σ(n)

类似于d(n)\mathbf{d(n)}d(n),约束和函数σ(n)\mathbf{\sigma(n)}σ(n)也有对应的表达式,设n=p1e1p2e2...pkek\mathbf{n=p_1^{e_1}p_2^{e_2}...p_k^{e_k}}n=p1e1​​p2e2​​...pkek​​,于是有σ(n)=(1+p11+p12+...+p1e1)(1+p21+p22+...+p2e2)...(1+pk1+pk2+...+pkek)\mathbf{\sigma(n)=(1+p_1^1+p_1^2+...+p_1^{e_1})(1+p_2^1+p_2^2+...+p_2^{e_2})...(1+p_k^1+p_k^2+...+p_k^{e_k})}σ(n)=(1+p11​+p12​+...+p1e1​​)(1+p21​+p22​+...+p2e2​​)...(1+pk1​+pk2​+...+pkek​​)。
证明也很简单,考虑σ(n)=∑d∣nd=∑d∣p1e1p2e2...pkekd=∑d1∣p1e1d1∑d2∣p2e2d2...∑dk∣pkekdk=∑i1=0e1p1i1∑i2=0e2p2i2...∑ik=0ekpkik\mathbf{\sigma(n)=\sum_{d\mid n}d=\sum_{d\mid p_1^{e_1}p_2^{e_2}...p_k^{e_k}}d=\sum_{d_1\mid p_1^{e_1}}d_1\sum_{d_2\mid p_2^{e_2}}d_2...\sum_{d_k\mid p_k^{e_k}}d_k=\sum_{i_1=0}^{e_1}p_1^{i_1}\sum_{i_2=0}^{e_2}p_2^{i_2}...\sum_{i_k=0}^{e_k}p_k^{i_k}}σ(n)=∑d∣n​d=∑d∣p1e1​​p2e2​​...pkek​​​d=∑d1​∣p1e1​​​d1​∑d2​∣p2e2​​​d2​...∑dk​∣pkek​​​dk​=∑i1​=0e1​​p1i1​​∑i2​=0e2​​p2i2​​...∑ik​=0ek​​pkik​​。

根据这个公式我们不难得到线性筛的三种情况下的式子。

  1. 当n为质数时,σ(n)=1+n\mathbf{\sigma(n)=1+n}σ(n)=1+n。
  2. 当np%p=0\mathbf{\frac np\%p=0}pn​%p=0时,设last\mathbf{last}last是np\mathbf{\frac np}pn​最小质数p的最高幂次对应的值,sum\mathbf{sum}sum则是np\mathbf{\frac np}pn​最小质因数p对σ(np)\mathbf{\sigma (\frac np)}σ(pn​)的所有贡献和,则σ(n)=σ(np)sum+last∗psum\mathbf{\sigma(n)=\sigma(\frac np)\frac{sum+last*p}{sum}}σ(n)=σ(pn​)sumsum+last∗p​
  3. 当np%p≠0\mathbf{\frac np\%p\ne 0}pn​%p​=0时,易得σ(n)=(1+p)σ(np)\mathbf{\sigma(n)=(1+p)\sigma(\frac np)}σ(n)=(1+p)σ(pn​)

3.狄利克雷卷积

(1).定义

定义关于f(n),g(n)\mathbf{f(n),g(n)}f(n),g(n)两个函数的卷积为h(n)\mathbf{h(n)}h(n),且h(n)=∑d∣nf(nd)g(d)\mathbf{h(n)=\sum_{d\mid n}f(\frac nd)g(d)}h(n)=∑d∣n​f(dn​)g(d),也可以记作h=f∗g\mathbf{h=f*g}h=f∗g或(f∗g)(n)=∑d∣nf(nd)g(d)\mathbf{(f*g)(n)=\sum_{d\mid n}f(\frac nd)g(d)}(f∗g)(n)=∑d∣n​f(dn​)g(d)。

(2).性质

  1. 交换律,即f∗g=g∗f\mathbf{f*g=g*f}f∗g=g∗f。
    证明:容易发现∑d∣nf(nd)g(d)=∑nd∣nf(d)g(nd)=∑d∣ng(nd)f(d)\mathbf{\sum_{d\mid n}f(\frac nd)g(d)=\sum_{\frac nd \mid n}f(d)g(\frac nd)=\sum_{d\mid n}g(\frac nd)f(d)}∑d∣n​f(dn​)g(d)=∑dn​∣n​f(d)g(dn​)=∑d∣n​g(dn​)f(d)。
  2. 结合律,即(f∗g)∗h=f∗(g∗h)\mathbf{(f*g)*h=f*(g*h)}(f∗g)∗h=f∗(g∗h)。
    证明:改变求和顺序并不会改变计算结果,故正确。
  3. 分配律,即(f+g)∗h=f∗h+g∗h\mathbf{(f+g)*h=f*h+g*h}(f+g)∗h=f∗h+g∗h。
    证明:∑d∣n(f(d)+g(d))h(nd)=∑d∣nf(d)h(nd)+∑d∣ng(d)h(nd)\mathbf{\sum_{d\mid n}(f(d)+g(d))h(\frac nd)=\sum_{d\mid n}f(d)h(\frac nd)+\sum_{d\mid n}g(d)h(\frac nd)}∑d∣n​(f(d)+g(d))h(dn​)=∑d∣n​f(d)h(dn​)+∑d∣n​g(d)h(dn​)。
  4. f∗ϵ=ϵ∗f=f\mathbf{f*\epsilon =\epsilon*f=f}f∗ϵ=ϵ∗f=f。
    证明:由于交换律成立,我们只需证明f∗ϵ=f\mathbf{f*\epsilon=f}f∗ϵ=f即可。直接列出定义式得到∑d∣nf(nd)[d=1]=f(n)\mathbf{\sum_{d\mid n}f(\frac nd)[d=1]=f(n)}∑d∣n​f(dn​)[d=1]=f(n)。

(3).常用卷积转化关系

  1. d=I∗I\mathbf{d=I*I}d=I∗I
    证明:(I∗I)(n)=∑d∣n1=d(n)\mathbf{(I*I)(n)=\sum_{d\mid n}1=d(n)}(I∗I)(n)=∑d∣n​1=d(n)。
  2. σ=id∗I\mathbf{\sigma =id*I}σ=id∗I
    证明:(id∗I)(n)=∑d∣nid(d)=∑d∣nd\mathbf{(id*I)(n)=\sum_{d\mid n}id(d)=\sum_{d\mid n}d}(id∗I)(n)=∑d∣n​id(d)=∑d∣n​d。
  3. ϵ=μ∗I\mathbf{\epsilon=\mu*I}ϵ=μ∗I
    证明:设n=p1a1p2a2...pkak,k>0\mathbf{n=p_1^{a_1}p_2^{a_2}...p_k^{a_k},k>0}n=p1a1​​p2a2​​...pkak​​,k>0,则(μ∗I)(n)=∑d∣p1a1p2a2...pkakμ(d)=∑d∣p1p2...pkμ(d)=∑i=0kCki(−1)i=(1−1)k=0k=0\mathbf{(\mu*I)(n)=\sum_{d\mid p_1^{a_1}p_2^{a_2}...p_k^{a_k}}\mu(d)=\sum_{d\mid p_1p_2...p_k}\mu(d)=\sum_{i=0}^kC_k^i(-1)^i=(1-1)^k=0^k=0}(μ∗I)(n)=∑d∣p1a1​​p2a2​​...pkak​​​μ(d)=∑d∣p1​p2​...pk​​μ(d)=∑i=0k​Cki​(−1)i=(1−1)k=0k=0,当n=1\mathbf{n=1}n=1时容易验证公式也是正确的。
  4. φ=μ∗id\mathbf{\varphi=\mu*id}φ=μ∗id
    证明:
    φ(n)=∑i=1n[gcd(i,n)=1]=∑i=1nϵ(gcd(i,n))=∑i=1n(μ∗I)(gcd(i,n))=∑i=1n∑d∣gcd(i,n)μ(d)=∑i=1n∑d∣i,d∣nμ(d)=∑d∣n,d∣i∑i=1nμ(d)=∑d∣nμ(d)∑i=1nd1=∑d∣nμ(d)nd=(μ∗id)(n)\mathbf{\begin{aligned}\varphi(n)&=\sum_{i=1}^n[gcd(i,n)=1]\\&=\sum_{i=1}^n\epsilon(gcd(i,n))\\&=\sum_{i=1}^n(\mu*I)(gcd(i,n))\\&=\sum_{i=1}^n\sum_{d\mid gcd(i,n)}\mu(d)\\&=\sum_{i=1}^n\sum_{d\mid i,d\mid n}\mu(d)\\&=\sum_{d\mid n,d\mid i}\sum_{i=1}^n\mu(d)\\&=\sum_{d\mid n}\mu(d)\sum_{i=1}^{ \frac nd}1\\&=\sum_{d\mid n}\mu(d)\frac nd=(\mu*id)(n)\end{aligned}}φ(n)​=i=1∑n​[gcd(i,n)=1]=i=1∑n​ϵ(gcd(i,n))=i=1∑n​(μ∗I)(gcd(i,n))=i=1∑n​d∣gcd(i,n)∑​μ(d)=i=1∑n​d∣i,d∣n∑​μ(d)=d∣n,d∣i∑​i=1∑n​μ(d)=d∣n∑​μ(d)i=1∑dn​​1=d∣n∑​μ(d)dn​=(μ∗id)(n)​
  5. id=φ∗I\mathbf{id=\varphi *I}id=φ∗I
    证明:根据转化关系4我们有φ∗I=μ∗id∗I=(μ∗I)∗id\mathbf{\varphi*I=\mu*id*I=(\mu*I)*id}φ∗I=μ∗id∗I=(μ∗I)∗id,又根据转化关系3我们有(μ∗I)∗id=ϵ∗id=id\mathbf{(\mu*I)*id=\epsilon*id=id}(μ∗I)∗id=ϵ∗id=id。

4.莫比乌斯反演定理

(1).基本内容

设F(n)=∑d∣nf(d)\mathbf{F(n)=\sum_{d\mid n}f(d)}F(n)=∑d∣n​f(d),则有f(n)=∑d∣nμ(d)F(nd)\mathbf{f(n)=\sum_{d\mid n}\mu(d)F(\frac nd)}f(n)=∑d∣n​μ(d)F(dn​)与其互推,一般可以简写为F=f∗I⇔f=μ∗F\mathbf{F=f*I\Leftrightarrow f=\mu*F}F=f∗I⇔f=μ∗F。
除此之外定理还有另一种表述形式,设F(n)=∑n∣df(d)\mathbf{F(n)=\sum_{n\mid d}f(d)}F(n)=∑n∣d​f(d),则f(n)=∑n∣dμ(dn)F(d)\mathbf{f(n)=\sum_{n\mid d}\mu(\frac dn)F(d)}f(n)=∑n∣d​μ(nd​)F(d)与其可互推。

(2).证明

考虑用狄利克雷卷积的转化关系直接证明。
由于F=f∗I\mathbf{F=f*I}F=f∗I,故F∗μ=f∗I∗μ=f∗ϵ=f\mathbf{F*\mu=f*I*\mu=f*\epsilon=f}F∗μ=f∗I∗μ=f∗ϵ=f,反推也同理。

(3).习题

莫比乌斯反演最主要的还是多练题,这里给出几道经典的题目提供练习。
例题一
题目来源:LuoGuP2522 [HAOI2011]Problem b
题面:

题解:将式子分成四块求解,每一块都是类似∑i=1a∑j=1b[gcd(i,j)=k]\mathbf{\sum_{i=1}^a\sum_{j=1}^b[gcd(i,j)=k]}∑i=1a​∑j=1b​[gcd(i,j)=k]的形式,下面是一些套路式的变换,第一次学的时候需要认真理解一下,整体来说不复杂,这里为了方便起见假设a≤b\mathbf{a\le b}a≤b
∑i=1a∑j=1b[gcd(i,j)=k]=∑i=1⌊ak⌋∑j=1⌊bk⌋[gcd(i,j)=1]......①=∑i=1⌊ak⌋∑j=1⌊bk⌋∑d∣i,d∣jμ(d).......套路一,ϵ=μ∗I代入式子=∑d=1⌊ak⌋μ(d)∑i=1⌊akd⌋∑j=1⌊bkd⌋1.......套路一,改变枚举顺序,这里是将d枚举提前,并且注意改变枚举顺序后仍然要符合d∣i,d∣j的条件=∑d=1⌊ak⌋μ(d)⌊akd⌋⌊bkd⌋\mathbf{\begin{aligned} \sum_{i=1}^a\sum_{j=1}^b[gcd(i,j)=k]&=\sum_{i=1}^{\lfloor \frac ak\rfloor}\sum_{j=1}^{\lfloor \frac bk\rfloor}[gcd(i,j)=1]......①\\ &= \sum_{i=1}^{\lfloor \frac ak\rfloor}\sum_{j=1}^{\lfloor \frac bk\rfloor}\sum_{d\mid i,d\mid j}\mu(d).......套路一,\epsilon=\mu*I代入式子\\ &= \sum_{d=1}^{\lfloor \frac ak\rfloor}\mu(d) \sum_{i=1}^{\lfloor \frac a{kd}\rfloor}\sum_{j=1}^{\lfloor \frac b{kd}\rfloor}1.......套路一,改变枚举顺序,这里是将d枚举提前,并且注意改变枚举顺序后仍然要符合d\mid i,d\mid j的条件\\ &=\sum_{d=1}^{\lfloor \frac ak\rfloor}\mu(d)\lfloor \frac a{kd}\rfloor\lfloor \frac b{kd}\rfloor \end{aligned}}i=1∑a​j=1∑b​[gcd(i,j)=k]​=i=1∑⌊ka​⌋​j=1∑⌊kb​⌋​[gcd(i,j)=1]......①=i=1∑⌊ka​⌋​j=1∑⌊kb​⌋​d∣i,d∣j∑​μ(d).......套路一,ϵ=μ∗I代入式子=d=1∑⌊ka​⌋​μ(d)i=1∑⌊kda​⌋​j=1∑⌊kdb​⌋​1.......套路一,改变枚举顺序,这里是将d枚举提前,并且注意改变枚举顺序后仍然要符合d∣i,d∣j的条件=d=1∑⌊ka​⌋​μ(d)⌊kda​⌋⌊kdb​⌋​
这里对于①处的变换作一下解释,我们枚举的是所有满足gcd(i,j)=k\mathbf{gcd(i,j)=k}gcd(i,j)=k的i,j\mathbf{i,j}i,j,我们不妨假设i=i′k,j=j′k\mathbf{i=i'k,j=j'k}i=i′k,j=j′k,显然有gcd(i′,j′)=1\mathbf{gcd(i',j')=1}gcd(i′,j′)=1,因此只需要枚举所有满足条件的i′,j′\mathbf{i',j'}i′,j′即可,不过注意i′,j′\mathbf{i',j'}i′,j′的取值范围相应地会发生改变,满足i=i′k≤a⇒i′≤ak⇒i′≤⌊ak⌋\mathbf{i=i'k\le a\Rightarrow i'\le \frac ak\Rightarrow i'\le \lfloor\frac ak\rfloor}i=i′k≤a⇒i′≤ka​⇒i′≤⌊ka​⌋,同理可得j′≤⌊bk⌋\mathbf{j'\le \lfloor \frac bk\rfloor}j′≤⌊kb​⌋,于是我们枚举满足gcd(i′,j′)=1\mathbf{gcd(i',j')=1}gcd(i′,j′)=1的所有i′,j′\mathbf{i',j'}i′,j′,显然它们对应的总数与满足gcd(i,j)=k\mathbf{gcd(i,j)=k}gcd(i,j)=k的i,j\mathbf{i,j}i,j的总数是一样的,故满足等式∑i=1a∑j=1b[gcd(i,j)=k]=∑i=1⌊ak⌋∑j=1⌊bk⌋[gcd(i,j)=1]\mathbf{\sum_{i=1}^a\sum_{j=1}^b[gcd(i,j)=k]=\sum_{i=1}^{\lfloor \frac ak\rfloor}\sum_{j=1}^{\lfloor \frac bk\rfloor}[gcd(i,j)=1]}∑i=1a​∑j=1b​[gcd(i,j)=k]=∑i=1⌊ka​⌋​∑j=1⌊kb​⌋​[gcd(i,j)=1]。

我们对最终的那个式子分块求解答案即可,这是因为⌊akd⌋⌊bkd⌋\mathbf{\lfloor \frac a{kd}\rfloor\lfloor \frac b{kd}\rfloor}⌊kda​⌋⌊kdb​⌋这一项在的取值范围是O(a)\mathbf{O(\sqrt a)}O(a​)的,故我们预处理出μ(n)\mathbf{\mu(n)}μ(n)的前缀和即可。

代码:

int prim[maxn],tot,flag[maxn],mu[maxn];
void init(int n){//线性筛预处理 mu[1]=1;FOR(i,2,n+1){if(!flag[i])prim[tot++]=i,mu[i]=-1;for(register int j=0;j<tot && prim[j]*i<=n;++j){flag[i*prim[j]]=1;if(i%prim[j]==0){mu[i*prim[j]]=0;break;}mu[i*prim[j]]=-mu[i];}}FOR(i,1,n+1)mu[i]+=mu[i-1];
}
ll solve(ll a,ll b,ll k){if(a>b)swap(a,b);ll ans=0;a/=k,b/=k;int i=1;while(i<=a){//分块 int j = min(a/(a/i),b/(b/i)); ans+=1ll*(mu[j]-mu[i-1])*(a/i)*(b/i);i=j+1;}return ans;
}
int main(){int a,b,c,d,k,t;init(maxn-1);rd(&t);while(t--){rd(&a,&b,&c,&d,&k);wrn(solve(b,d,k)-solve(a-1,d,k)-solve(b,c-1,k)+solve(a-1,c-1,k));}
}

例题二
题目来源:LuoGuP1891 疯狂 LCM
题面:

题解:先设gcd(i,n)=d\mathbf{gcd(i,n)=d}gcd(i,n)=d,我们容易得到∑i=1nlcm(i,n)=∑i=1nind[gcd(i,n)=d]=∑d∣n∑i=1ndin[gcd(i,nd)=1]=n∑d∣ndφ(d)+[d=1]2......这个变换在欧拉函数一节中有证明与介绍=n(∑d∣ndφ(d)+1)2\mathbf{\begin{aligned}\sum_{i=1}^nlcm(i,n)&=\sum_{i=1}^n\frac{in}d[gcd(i,n)=d]\\&=\sum_{d\mid n}\sum_{i=1}^{\frac nd}in[gcd(i,\frac nd)=1]\\&=n\sum_{d\mid n}\frac{d\varphi(d)+[d=1]}{2}......这个变换在欧拉函数一节中有证明与介绍\\&=n\frac{(\sum_{d\mid n}d\varphi(d)+1)}2\end{aligned}}i=1∑n​lcm(i,n)​=i=1∑n​din​[gcd(i,n)=d]=d∣n∑​i=1∑dn​​in[gcd(i,dn​)=1]=nd∣n∑​2dφ(d)+[d=1]​......这个变换在欧拉函数一节中有证明与介绍=n2(∑d∣n​dφ(d)+1)​​。
设f(n)=∑d∣ndφ(d)\mathbf{f(n)=\sum_{d\mid n}d\varphi(d)}f(n)=∑d∣n​dφ(d),则f(n)\mathbf{f(n)}f(n)是一个积性函数,由于这个积性函数不太好筛,这里给出当np%p=0\mathbf{\frac np\%p=0}pn​%p=0的情况的递推式推导过程。首先f(pk)=∑i=0kp2i−1(p−1),i=0的时候先忽视,后面会发现这个不影响结果\mathbf{f(p^k)=\sum_{i=0}^kp^{2i-1}(p-1),i=0的时候先忽视,后面会发现这个不影响结果}f(pk)=∑i=0k​p2i−1(p−1),i=0的时候先忽视,后面会发现这个不影响结果,然后我们假设np=apk\mathbf{\frac np=ap^k}pn​=apk,于是有f(np)=f(a)f(pk),f(np2)=f(a)f(pk−1)\mathbf{f(\frac np)=f(a)f(p^k),f(\frac n{p^2})=f(a)f(p^{k-1})}f(pn​)=f(a)f(pk),f(p2n​)=f(a)f(pk−1),将两式子相减得到f(np)−f(np2)=f(a)[f(pk)−f(pk−1)]=f(a)p2k−1(p−1)\mathbf{f(\frac np)-f(\frac n{p^2})=f(a)[f(p^k)-f(p^{k-1})]=f(a)p^{2k-1}(p-1)}f(pn​)−f(p2n​)=f(a)[f(pk)−f(pk−1)]=f(a)p2k−1(p−1),同理能够得到f(n)−f(np)=f(a)p2k+1(p−1)\mathbf{f(n)-f(\frac np)=f(a)p^{2k+1}(p-1)}f(n)−f(pn​)=f(a)p2k+1(p−1),于是有f(n)=f(np)+[f(np)−f(np2)]p2\mathbf{f(n)=f(\frac np)+[f(\frac np)-f(\frac n{p^2})]p^2}f(n)=f(pn​)+[f(pn​)−f(p2n​)]p2,利用这个式子我们就可以愉快地筛除整个f数列了!
代码:

int prim[maxn],flag[maxn],tot;
ll f[maxn];
void init(int n){f[1]=1;FOR(i,2,n+1){if(!flag[i])prim[tot++]=i,f[i]=1+1ll*i*(i-1);for(register int j=0;j<tot && prim[j]*i<=n;++j){flag[i*prim[j]]=1;if(i%prim[j]==0){f[i*prim[j]]=f[i]+1ll*(f[i]-f[i/prim[j]])*prim[j]*prim[j];break;}f[i*prim[j]]=f[i]+1ll*f[i]*prim[j]*(prim[j]-1); }}
}
int main(){init(maxn-1);int t;rd(&t);while(t--){int n;rd(&n);ll ans=f[n]+1;wrn(ans/2ll*n);}
}

例题三
题目来源:LuoGuP1829 [国家集训队]Crash的数字表格 / JZPTAB
题面:

题解:还是一阵套路推式子,假设n≤m\mathbf{n\le m}n≤m,则有
∑i=1n∑j=1mlcm(i,j)=∑d∣n,d∣m∑i=1n∑j=1mijd[gcd(i,j)=d]=∑d∣n,d∣m∑i=1nd∑j=1mdijd[gcd(i,j)=1]=∑d∣n,d∣md∑i=1nd∑j=1mdij[gcd(i,j)=1]=∑d∣n,d∣md∑i=1nd∑j=1mdij∑d′∣i,d′∣jμ(d′)=∑d∣n,d∣md∑d′=1ndd′2μ(d′)∑i=1⌊ndd′⌋i∑j=1⌊mdd′⌋j=∑d∣n,d∣md∑d′=1ndd′2μ(d′)sum(⌊ndd′⌋,⌊mdd′⌋)......令sum(⌊ndd′⌋,⌊mdd′⌋)=∑i=1ndd′i∑j=1mdd′j\mathbf{\begin{aligned} \sum_{i=1}^n\sum_{j=1}^mlcm(i,j)&=\sum_{d\mid n,d\mid m}\sum_{i=1}^n\sum_{j=1}^m\frac {ij}d[gcd(i,j)=d]\\ &=\sum_{d\mid n,d\mid m}\sum_{i=1}^{\frac nd }\sum_{j=1}^{\frac md}ijd[gcd(i,j)=1]\\ &=\sum_{d\mid n,d\mid m}d\sum_{i=1}^{\frac nd }\sum_{j=1}^{\frac md}ij[gcd(i,j)=1]\\ &=\sum_{d\mid n,d\mid m}d\sum_{i=1}^{\frac nd }\sum_{j=1}^{\frac md}ij\sum_{d'\mid i,d'\mid j}\mu(d')\\ &=\sum_{d\mid n,d\mid m}d\sum_{d'=1}^{\frac nd}{d'}^2\mu(d')\sum_{i=1}^{\lfloor \frac n{dd'}\rfloor }i\sum_{j=1}^{\lfloor \frac m{dd'}\rfloor}j\\ &=\sum_{d\mid n,d\mid m}d\sum_{d'=1}^{\frac nd}{d'}^2\mu(d')sum(\lfloor \frac n{dd'}\rfloor ,\lfloor \frac m{dd'}\rfloor)......令sum(\lfloor \frac n{dd'}\rfloor ,\lfloor \frac m{dd'}\rfloor)=\sum_{i=1}^{\frac n{dd'}}i\sum_{j=1}^{\frac m{dd'}}j\\ \end{aligned}}i=1∑n​j=1∑m​lcm(i,j)​=d∣n,d∣m∑​i=1∑n​j=1∑m​dij​[gcd(i,j)=d]=d∣n,d∣m∑​i=1∑dn​​j=1∑dm​​ijd[gcd(i,j)=1]=d∣n,d∣m∑​di=1∑dn​​j=1∑dm​​ij[gcd(i,j)=1]=d∣n,d∣m∑​di=1∑dn​​j=1∑dm​​ijd′∣i,d′∣j∑​μ(d′)=d∣n,d∣m∑​dd′=1∑dn​​d′2μ(d′)i=1∑⌊dd′n​⌋​ij=1∑⌊dd′m​⌋​j=d∣n,d∣m∑​dd′=1∑dn​​d′2μ(d′)sum(⌊dd′n​⌋,⌊dd′m​⌋)......令sum(⌊dd′n​⌋,⌊dd′m​⌋)=i=1∑dd′n​​ij=1∑dd′m​​j​
上面这个式子已经可以直接做出这道题了,令g(n,m)=∑d=1nd2μ(d)sum(⌊nd⌋,⌊md⌋)\mathbf{g(n,m)=\sum_{d=1}^nd^2\mu(d)sum(\lfloor \frac nd\rfloor,\lfloor \frac md\rfloor)}g(n,m)=∑d=1n​d2μ(d)sum(⌊dn​⌋,⌊dm​⌋),我们发现这个式子可以分块求,其中sum(n,m)=n(n+1)2⋅m(m+1)2\mathbf{sum(n,m)=\frac{n(n+1)}2\cdot \frac{m(m+1)}2}sum(n,m)=2n(n+1)​⋅2m(m+1)​,然后我们最终要求的是∑d∣n,d∣mdg(nd,md)\mathbf{\sum_{d\mid n,d\mid m}dg(\frac nd,\frac md)}∑d∣n,d∣m​dg(dn​,dm​),其等价于∑d=1ndg(⌊nd⌋,⌊md⌋)\mathbf{\sum_{d=1}^ndg(\lfloor \frac nd\rfloor,\lfloor \frac md\rfloor)}∑d=1n​dg(⌊dn​⌋,⌊dm​⌋),这个式子显然也可以分块求,分析一下复杂度显然是小于O(n)\mathbf{O(n)}O(n)的。
不过还有另一种方法也可以求,我们继续从刚才的位置往下推:
∑i=1n∑j=1mlcm(i,j)=∑d∣n,d∣md∑d′=1ndd′2μ(d′)sum(⌊ndd′⌋,⌊mdd′⌋)=∑d∣n,d∣md∑d′=1ndd′2μ(d′)sum(⌊nT⌋,⌊mT⌋)........令T=dd′=∑T=1nsum(⌊nT⌋,⌊mT⌋)∑d′∣TTd′d′2μ(d′)=∑T=1nsum(⌊nT⌋,⌊mT⌋)T∑d∣Tdμ(d)\mathbf{\begin{aligned} \sum_{i=1}^n\sum_{j=1}^mlcm(i,j)&=\sum_{d\mid n,d\mid m}d\sum_{d'=1}^{\frac nd}{d'}^2\mu(d')sum(\lfloor \frac n{dd'}\rfloor ,\lfloor \frac m{dd'}\rfloor)\\ &=\sum_{d\mid n,d\mid m}d\sum_{d'=1}^{\frac nd}d'^2\mu(d')sum(\lfloor \frac nT\rfloor,\lfloor \frac mT\rfloor)........令T=dd'\\ &=\sum_{T=1}^nsum(\lfloor \frac nT\rfloor,\lfloor \frac mT\rfloor)\sum_{d'\mid T}\frac T{d'}d'^2\mu(d')\\ &=\sum_{T=1}^nsum(\lfloor \frac nT\rfloor,\lfloor \frac mT\rfloor)T\sum_{d\mid T}d\mu(d)\\ \end{aligned} }i=1∑n​j=1∑m​lcm(i,j)​=d∣n,d∣m∑​dd′=1∑dn​​d′2μ(d′)sum(⌊dd′n​⌋,⌊dd′m​⌋)=d∣n,d∣m∑​dd′=1∑dn​​d′2μ(d′)sum(⌊Tn​⌋,⌊Tm​⌋)........令T=dd′=T=1∑n​sum(⌊Tn​⌋,⌊Tm​⌋)d′∣T∑​d′T​d′2μ(d′)=T=1∑n​sum(⌊Tn​⌋,⌊Tm​⌋)Td∣T∑​dμ(d)​
然后我们令f(n)=n∑d∣ndμ(d)\mathbf{f(n)=n\sum_{d\mid n}d\mu(d)}f(n)=n∑d∣n​dμ(d),显然f\mathbf{f}f是一个积性函数,可以用线性筛筛出来,然后我们要算的式子其实就是∑T=1nsum(⌊nT⌋,⌊mT⌋)f(T)\mathbf{\sum_{T=1}^nsum(\lfloor \frac nT\rfloor,\lfloor \frac mT\rfloor)f(T)}∑T=1n​sum(⌊Tn​⌋,⌊Tm​⌋)f(T),对f\mathbf{f}f求个前缀和后就可以愉快地分块了,然后就这个式子而言复杂度是O(n)\mathbf{O(\sqrt n)}O(n​)的,不过线性筛的复杂度提高了上限,所以复杂度是O(n)\mathbf{O(n)}O(n),不过这个式子显然比上一个式子更清爽,这里的代码也是用的第二个式子,然后没加什么优化跑出了洛谷第六的成绩。
代码:

const int mod = 20101009;
int prim[maxn],flag[maxn],tot,f[maxn],sum[maxn];
void init(int n,int m){f[1]=1;sum[1]=1;FOR(i,2,n+1){sum[i]=(sum[i-1]+i)%mod;if(!flag[i])prim[tot++]=i,f[i]=1-i;for(register int j= 0;j<tot && prim[j]*i<=n;++j){flag[i*prim[j]]=1;if(i%prim[j]==0){f[i*prim[j]]=f[i];break;} f[i*prim[j]]=1ll*f[i]*(1-prim[j])%mod;}}FOR(i,n+1,m+1)sum[i]=(sum[i-1]+i)%mod;FOR(i,1,n+1)f[i]=1ll*i*f[i]%mod,f[i]=(f[i]+f[i-1])%mod;
}
int main(){int n,m;rd(&n,&m);if(n>m)swap(n,m);init(n,m); int i=1,j;ll ans=0;while(i<=n){j = min(n/(n/i),m/(m/i));ans=(ans+1ll*(f[j]-f[i-1])*sum[n/i]%mod*sum[m/i])%mod;i=j+1;}ans=(ans%mod+mod)%mod;wrn(ans);
}

例题四
题目来源:LuoGuP3327 [SDOI2015]约数个数和
题面:

题解:首先需要知道一个结论,d(ij)=∑x∣i∑y∣j[gcd(x,y)=1]\mathbf{d(ij)=\sum_{x\mid i}\sum_{y\mid j}[gcd(x,y)=1]}d(ij)=∑x∣i​∑y∣j​[gcd(x,y)=1]。
如何证明这个结论呢,我们先看看ij\mathbf{ij}ij的因子是如何被构造出来的,假设ij=p1a1p2a2...pkak\mathbf{ij=p_1^{a_1}p_2^{a_2}...p_k^{a_k}}ij=p1a1​​p2a2​​...pkak​​,我们将这个数拆分成k\mathbf{k}k个组,你可以想象为k个盒子,第i个盒子里装着pi0,pi1,...,piai\mathbf{p_i^0,p_i^1,...,p_i^{a_i}}pi0​,pi1​,...,piai​​(i∈[1,k]\mathbf{i\in[1,k]}i∈[1,k]),这样我们从每个盒子里选一个数,乘起来后就能组成ij\mathbf{ij}ij的唯一的因子,这也是ij\mathbf{ij}ij因子的构造方式,它能够做到不重不漏地表示出ij\mathbf{ij}ij的因子,现在我们把这些盒子称作ij\mathbf{ij}ij的盒子组,那么如何分别根据i\mathbf{i}i的盒子组和j\mathbf{j}j的盒子组来构造ij\mathbf{ij}ij的因子呢?一个简单的想法是我们考虑从i\mathbf{i}i的盒子组的一些盒子中拿一些数再从j\mathbf{j}j的盒子组中拿一些数让后把它们乘起来构造因子,不过这个想法有个致命的缺陷,虽然它能够表示出ij\mathbf{ij}ij所有的因子,但是它表示的因子会出现重复,原因也很简单,因为一个质数的幂次的组成方式是不唯一的。那么如何才能不漏不重地表示出ij\mathbf{ij}ij的因子呢?参考我们从ij\mathbf{ij}ij盒子组中构造因子的方式,那么现在我们把ij\mathbf{ij}ij分成了i\mathbf{i}i和j\mathbf{j}j其实构造因子的方式还是一样的,我们可以把i\mathbf{i}i和j\mathbf{j}j的盒子组看成一个整体,假设i\mathbf{i}i的第k\mathbf{k}k个盒子中有ak\mathbf{a_k}ak​个数,j\mathbf{j}j的第k\mathbf{k}k个盒子中有bk\mathbf{b_k}bk​个数,如果将这两个盒子看成一个盒子那么就有ak+bk\mathbf{a_k+b_k}ak​+bk​个数,我们总共有ak+bk\mathbf{a_k+b_k}ak​+bk​种选择的方式,当选择c(c≤ak)\mathbf{c(c\le a_k)}c(c≤ak​)个数的时候我们约定只从i\mathbf{i}i的这个盒子中拿数,当选择c(c>ak)\mathbf{c(c>a_k)}c(c>ak​)个数的时候我们约定只从j\mathbf{j}j的这个盒子中拿数,这样就保证了每次拿数的方式唯一确定,最终形成的因子也是唯一确定的,这相当于是一个映射(仔细体会)。然后将这个拿数的方式转化为数学公式也很简单,我们拿i\mathbf{i}i盒子的时候就不会拿j\mathbf{j}j盒子,我们拿j\mathbf{j}j盒子的时候就不会拿i\mathbf{i}i盒子,这意味着在i\mathbf{i}i中拿出的数与在j\mathbf{j}j中拿出的数的最大公因数是1,也就是公式中所展示的gcd(x,y)=1\mathbf{gcd(x,y)=1}gcd(x,y)=1,而x,y\mathbf{x,y}x,y分别表示在i,j\mathbf{i,j}i,j盒子中拿出的数的乘积。

现在我们把这个结论化简一下:
d(ij)=∑x∣i∑y∣j[gcd(x,y)=1]=∑x∣i∑y∣j∑d∣x,d∣yμ(d)=∑d∣i,d∣jμ(d)∑x∣i[d∣x]∑y∣j[d∣y]=∑d∣i,d∣jμ(d)∑x∣id∑y∣jd1..........①=∑d∣i,d∣jμ(d)d(id)d(jd)\mathbf{\begin{aligned} d(ij)&=\sum_{x\mid i}\sum_{y\mid j}[gcd(x,y)=1]\\ &=\sum_{x\mid i}\sum_{y\mid j}\sum_{d\mid x,d\mid y}\mu(d)\\ &=\sum_{d\mid i,d\mid j}\mu(d)\sum_{x\mid i}[d\mid x]\sum_{y\mid j}[d\mid y]\\ &=\sum_{d\mid i,d\mid j}\mu(d)\sum_{x\mid \frac id}\sum_{y\mid \frac jd}1..........①\\ &=\sum_{d\mid i,d\mid j}\mu(d)d(\frac id)d(\frac jd)\\ \end{aligned}}d(ij)​=x∣i∑​y∣j∑​[gcd(x,y)=1]=x∣i∑​y∣j∑​d∣x,d∣y∑​μ(d)=d∣i,d∣j∑​μ(d)x∣i∑​[d∣x]y∣j∑​[d∣y]=d∣i,d∣j∑​μ(d)x∣di​∑​y∣dj​∑​1..........①=d∣i,d∣j∑​μ(d)d(di​)d(dj​)​
这里特别说明一下①处是如何转化过去的,我们以∑d∣iμ(d)∑x∣i[d∣x]\mathbf{\sum_{d\mid i}\mu(d)\sum_{x\mid i}[d\mid x]}∑d∣i​μ(d)∑x∣i​[d∣x]为例解释,y\mathbf{y}y的原理相同。首先我们要化简x\mathbf{x}x的枚举量,x对应的约束条件是d∣i,d∣x,x∣i\mathbf{d\mid i,d\mid x,x\mid i}d∣i,d∣x,x∣i,由前两个我们容易知道d∣gcd(x,i)\mathbf{d\mid gcd(x,i)}d∣gcd(x,i),结合x∣i\mathbf{x\mid i}x∣i,我们有xd∣id\mathbf{\frac xd\mid \frac id}dx​∣di​ ,然后我们直接枚举x′=xd\mathbf{x'=\frac xd}x′=dx​即可,那么x\mathbf{x}x由x=x′d\mathbf{x=x'd}x=x′d唯一确定,转化枚举量后容易得到∑d∣iμ(d)∑x′∣id1\mathbf{\sum_{d\mid i}\mu(d)\sum_{x'\mid \frac id}1}∑d∣i​μ(d)∑x′∣di​​1,然后把x′\mathbf{x'}x′写成x\mathbf{x}x后就得到了我们想要的化简形式。

现在我们开始最后的套路部分,将d(ij)\mathbf{d(ij)}d(ij)的化简表达式代入后跟前面的例题差别不大,这里仍然假设n≤m\mathbf{n\le m}n≤m。
∑i=1n∑j=1md(ij)=∑i=1n∑j=1m∑d∣i,d∣jμ(d)d(id)d(jd)=∑d=1nμ(d)∑i=1⌊nd⌋d(i)∑j=1⌊md⌋d(j)=∑d=1nμ(d)sum(⌊nd⌋)sum(⌊md⌋)\mathbf{\begin{aligned} \sum_{i=1}^n\sum_{j=1}^md(ij)&=\sum_{i=1}^n\sum_{j=1}^m\sum_{d\mid i,d\mid j}\mu(d)d(\frac id)d(\frac jd)\\ &=\sum_{d=1}^n\mu(d)\sum_{i=1}^{\lfloor \frac nd\rfloor}d(i)\sum_{j=1}^{\lfloor \frac md\rfloor}d(j)\\ &=\sum_{d=1}^n\mu(d)sum(\lfloor \frac nd \rfloor)sum(\lfloor \frac md\rfloor) \end{aligned}}i=1∑n​j=1∑m​d(ij)​=i=1∑n​j=1∑m​d∣i,d∣j∑​μ(d)d(di​)d(dj​)=d=1∑n​μ(d)i=1∑⌊dn​⌋​d(i)j=1∑⌊dm​⌋​d(j)=d=1∑n​μ(d)sum(⌊dn​⌋)sum(⌊dm​⌋)​
我们发现预处理一下d(n)\mathbf{d(n)}d(n)的前缀和即可,具体如何线性筛d(n)\mathbf{d(n)}d(n)见第十部分2.(4).[2]。
代码:

int prim[maxn],tot,d[maxn],e[maxn],mu[maxn];
ll sum[maxn];
void init(int n){bitset<maxn>flag;d[1]=mu[1]=1;FOR(i,2,n+1){if(!flag[i])prim[tot++]=i,e[i]=d[i]=2,mu[i]=-1;for(register int j=0;j<tot && prim[j]*i<=n;++j){flag[i*prim[j]]=1;if(i%prim[j]==0){d[i*prim[j]]=d[i]+d[i]/e[i];e[i*prim[j]]=e[i]+1;break;}d[i*prim[j]]=d[i]*2;e[i*prim[j]]=2;mu[i*prim[j]]=-mu[i]; } }FOR(i,1,n+1)sum[i]=sum[i-1]+d[i],mu[i]+=mu[i-1];
}int main(){int t;init(maxn-1);rd(&t);while(t--){int n,m;rd(&n,&m);if(n>m)swap(n,m); int i=1,j;ll ans=0;while(i<=n){j=min(n/(n/i),m/(m/i));ans+=(mu[j]-mu[i-1])*sum[n/i]*sum[m/i];i=j+1;}wrn(ans);}
}

例题五
题目来源:LuoGuP4449 于神之怒加强版
题面:

题解:跟上面的做法差不多,这里不推式子了,基本都是那个套路,可以作为练习巩固一下。
代码:

const ll mod = 1e9+7;
ll prim[maxn],tot,f[maxn],pk[maxn];void init(int n,int k){bitset<maxn>flag;f[1]=1;FOR(i,2,n+1){if(!flag[i])prim[tot++]=i,pk[tot-1]=qpow(i,k,mod),f[i]=pk[tot-1]-1;for(register int j= 0;j<tot && prim[j]*i<=n;++j){flag[i*prim[j]]=1;if(i%prim[j]==0){f[i*prim[j]]=f[i]*pk[j]%mod;break;}f[i*prim[j]]=f[i]*(pk[j]-1)%mod;}}FOR(i,2,n+1)f[i]=(f[i]+f[i-1])%mod;
}
int main(){int t,k;rd(&t,&k);init(maxn-1,k);while(t--){int n,m;rd(&n,&m);int i =1,j;ll ans=0;if(n>m)swap(n,m);while(i<=n){j=min(n/(n/i),m/(m/i));ans=(ans+1ll*(n/i)*(m/i)%mod*(f[j]-f[i-1])%mod)%mod;i=j+1;}ans=(ans%mod+mod)%mod;wrn(ans);}
}

5.特殊筛法

下面介绍的三种筛法都属于亚线性筛,能够在低于线性复杂度的时间内求解出数论函数的前缀和,一般而言都是求解积性函数的前缀和,即求解出S(n)=∑i=1nf(i)\mathbf{S(n)=\sum_{i=1}^nf(i)}S(n)=∑i=1n​f(i)的值。

(1).杜教筛

[1].原理介绍

f\mathbf{f}f函数的前缀和不好求,我们不妨考虑让f\mathbf{f}f与另一个函数g\mathbf{g}g狄利克雷卷积得到f∗g\mathbf{f*g}f∗g,如果f∗g\mathbf{f*g}f∗g与g\mathbf{g}g的前缀和好求的话那就有办法搞出f\mathbf{f}f的前缀和。
因为
∑i=1n(f∗g)(i)=∑i=1n∑d∣ig(d)f(id)=∑d=1n∑i=1⌊nd⌋g(d)f(i)=∑d=1ng(d)∑i=1⌊nd⌋f(i)=∑i=1ng(i)S(⌊ni⌋)=∑i=2ng(i)S(⌊ni⌋)+g(1)S(n)\mathbf{\begin{aligned} \sum_{i=1}^n(f*g)(i)&=\sum_{i=1}^n\sum_{d\mid i}g(d)f(\frac id)\\ &=\sum_{d=1}^n\sum_{i=1}^{\lfloor \frac nd\rfloor}g(d)f(i)\\ &=\sum_{d=1}^ng(d)\sum_{i=1}^{\lfloor \frac nd\rfloor}f(i)\\ &=\sum_{i=1}^ng(i)S(\lfloor \frac ni\rfloor)\\ &=\sum_{i=2}^ng(i)S(\lfloor \frac ni\rfloor)+g(1)S(n) \end{aligned}}i=1∑n​(f∗g)(i)​=i=1∑n​d∣i∑​g(d)f(di​)=d=1∑n​i=1∑⌊dn​⌋​g(d)f(i)=d=1∑n​g(d)i=1∑⌊dn​⌋​f(i)=i=1∑n​g(i)S(⌊in​⌋)=i=2∑n​g(i)S(⌊in​⌋)+g(1)S(n)​
于是我们得到了g(1)S(n)=∑i=1n(f∗g)(i)−∑i=2ng(i)S(⌊nd⌋)\mathbf{g(1)S(n)=\sum_{i=1}^n(f*g)(i)-\sum_{i=2}^ng(i)S(\lfloor \frac nd\rfloor)}g(1)S(n)=∑i=1n​(f∗g)(i)−∑i=2n​g(i)S(⌊dn​⌋),g(1)\mathbf{g(1)}g(1)一般是一个非零常值,显然如果要计算S(n)\mathbf{S(n)}S(n)的话需要能快速得到f∗g\mathbf{f*g}f∗g的前缀和以及g\mathbf{g}g的前缀和,其中g\mathbf{g}g的前缀和用于∑i=2ng(i)S(⌊nd⌋)\mathbf{\sum_{i=2}^ng(i)S(\lfloor \frac nd\rfloor)}∑i=2n​g(i)S(⌊dn​⌋)进行分块,根据第十部分1.(1).1我们知道只需要预处理出n1,n2,...,nn\mathbf{\frac n1,\frac n2,...,\frac nn}1n​,2n​,...,nn​的值(只有约2⌊n⌋\mathbf{2\lfloor \sqrt n\rfloor}2⌊n​⌋种),然后S(n)\mathbf{S(n)}S(n)就可以在这些值之间递推,最终能够得到S(n)\mathbf{S(n)}S(n)的值。

这里给出关于杜教筛复杂度的结论,证明参考这里。
如果不用线性筛预处理一部分前缀和的话复杂度是O(n34)\mathbf{O(n^{\frac 34})}O(n43​),然后可以证明预处理出n23\mathbf{n^{\frac 23}}n32​的前缀和数组后可以让复杂度降至O(n23)\mathbf{O(n^{\frac 23})}O(n32​)。

[2].习题

例题一
题目来源:LuoGuP4213 【模板】杜教筛(Sum)
题面:

题解:注意到φ∗I=id,μ∗I=ϵ\mathbf{\varphi*I=id,\mu*I=\epsilon}φ∗I=id,μ∗I=ϵ,而∑i=1nid(i)=n(n+1)2,∑i=1nϵ(i)=1\mathbf{\sum_{i=1}^nid(i)=\frac{n(n+1)}2,\sum_{i=1}^n\epsilon(i)=1}∑i=1n​id(i)=2n(n+1)​,∑i=1n​ϵ(i)=1,设φ和μ\mathbf{\varphi和\mu}φ和μ的前缀和分别是S1,S2\mathbf{S1,S2}S1,S2,根据杜教筛的公式不难得到S1(n)=n(n+1)2−∑i=2nS1(⌊ni⌋),S2(n)=1−∑i=2nS2(⌊ni⌋)\mathbf{S1(n)=\frac{n(n+1)}2-\sum_{i=2}^nS1(\lfloor \frac ni\rfloor),S2(n)=1-\sum_{i=2}^nS2(\lfloor \frac ni\rfloor)}S1(n)=2n(n+1)​−∑i=2n​S1(⌊in​⌋),S2(n)=1−∑i=2n​S2(⌊in​⌋),于是就可以利用递归求解了,不过需要预处理n23\mathbf{n^{\frac 23}}n32​范围内的前缀和才能过本题,然后还有个优化就是考虑使用unordered_map(你也可以手写哈希表,不过实测效率无明显提升)记录算过的S1,S2\mathbf{S1,S2}S1,S2 的值,类似于dp那样。

以上是常规做法,本题还有一个大的优化,我们看S1\mathbf{S1}S1似乎可以反演一下,因为φ=μ∗id\mathbf{\varphi=\mu*id}φ=μ∗id,于是有:
∑i=1nφ(n)=∑i=1n∑d∣iμ(d)id=∑d=1nμ(d)∑i=1⌊nd⌋i=∑d=1μ(d)⌊nd⌋(⌊nd⌋+1)2\mathbf{\begin{aligned} \sum_{i=1}^n\varphi(n)&=\sum_{i=1}^n\sum_{d\mid i}\mu(d)\frac id\\ &=\sum_{d=1}^n\mu(d)\sum_{i=1}^{\lfloor \frac nd\rfloor}i\\ &=\sum_{d=1}\mu(d)\frac{\lfloor \frac nd\rfloor(\lfloor \frac nd\rfloor+1)}{2} \end{aligned}}i=1∑n​φ(n)​=i=1∑n​d∣i∑​μ(d)di​=d=1∑n​μ(d)i=1∑⌊dn​⌋​i=d=1∑​μ(d)2⌊dn​⌋(⌊dn​⌋+1)​​
根据这个式子我们发现只需要能够求出S2\mathbf{S2}S2就能O(n)\mathbf{O(\sqrt n)}O(n​)的求出S1\mathbf{S1}S1了。然后我们就能跑出非常优秀的一个时限,这里给出这个更优秀的方法的代码,对S1\mathbf{S1}S1用莫比乌斯反演,对S2\mathbf{S2}S2用杜教筛。

代码:

ll s1[maxn];
int n,s2[maxn],prim[maxn];
unordered_map<int,ll>mp;
void init(int n){bitset<maxn>flag;s1[1]=s2[1]=1;register int tot=0;FOR(i,2,n+1){if(!flag[i])prim[tot++]=i,s1[i]=i-1,s2[i]=-1;for(register int j = 0;j<tot && prim[j]*i<=n;++j){flag[i*prim[j]]=1;if(i%prim[j]==0){s1[i*prim[j]]=s1[i]*prim[j];break;}s1[i*prim[j]]=s1[i]*(prim[j]-1);s2[i*prim[j]]=-s2[i];}}FOR(i,1,n+1)s1[i]+=s1[i-1],s2[i]+=s2[i-1];
}
ll sm1(int n){return 1ll*n*(n+1);
}
ll S2(int n){if(n<maxn)return s2[n];if(mp.count(n))return mp[n];register ll ans=1;register int i=2,j;while(i<=n){j=n/(n/i);ans-=(j-i+1)*S2(n/i);i=j+1;}return mp[n]=ans;
}
ll S1(int n){if(n<maxn)return s1[n];register ll ans=0;register int i = 1,j;while(i<=n){j=n/(n/i);ans+=sm1(n/i)*(S2(j)-S2(i-1));i=j+1;}return ans>>1;
}
int main(){vector<int>qry;int t,mx=0;rd(&t);while(t--){rd(&n);qry.push_back(n);mx=max(mx,n);}init(min(maxn-1,mx));FOR(i,0,qry.size()){n=qry[i];ll ans2=S2(n),ans1=S1(n);wrn(ans1,ans2);}
}

例题二
题目来源:LuoGuP3768 简单的数学题
题面:

题解:先反演一波。
∑i=1n∑j=1nijgcd(i,j)=∑k=1n∑i=1n∑j=1nijk[gcd(i,j)=k]=∑k=1nk3∑i=1⌊nk⌋∑j=1⌊nk⌋ij∑d∣i,d∣jμ(d)=∑k=1nk3∑d=1⌊nk⌋d2μ(d)∑i=1⌊nkd⌋∑j=1⌊nkd⌋ij=∑k=1nk3∑d=1⌊nk⌋d2μ(d)sum(⌊nkd⌋)2......sum(n)=n(n+1)2=∑T=1nsum(⌊nT⌋)2∑k∣Tk3(Tk)2μ(Tk)......令T=kd=∑i=1nsum(⌊ni⌋)2i2∑d∣idμ(id)=∑i=1nsum(⌊ni⌋)2f(i)......令f(i)=i2∑d∣idμ(id)=i2φ(i)\mathbf{\begin{aligned} \sum_{i=1}^n\sum_{j=1}^nijgcd(i,j)&=\sum_{k=1}^n\sum_{i=1}^n\sum_{j=1}^nijk[gcd(i,j)=k]\\ &=\sum_{k=1}^nk^3\sum_{i=1}^{\lfloor \frac nk\rfloor}\sum_{j=1}^{\lfloor \frac nk\rfloor}ij\sum_{d\mid i,d\mid j}\mu(d)\\ &=\sum_{k=1}^nk^3\sum_{d=1}^{\lfloor \frac nk\rfloor}d^2\mu(d)\sum_{i=1}^{\lfloor \frac n{kd}\rfloor}\sum_{j=1}^{\lfloor \frac n{kd}\rfloor}ij\\ &=\sum_{k=1}^nk^3\sum_{d=1}^{\lfloor \frac nk\rfloor}d^2\mu(d)sum(\lfloor \frac n{kd}\rfloor)^2......sum(n)=\frac{n(n+1)}2\\ &=\sum_{T=1}^nsum(\lfloor \frac n{T}\rfloor)^2\sum_{k\mid T}k^3{(\frac Tk)}^2\mu(\frac Tk)......令T=kd\\ &=\sum_{i=1}^nsum(\lfloor \frac n{i}\rfloor)^2i^2\sum_{d\mid i}d\mu(\frac id)\\ &=\sum_{i=1}^nsum(\lfloor \frac n{i}\rfloor)^2f(i)......令f(i)=i^2\sum_{d\mid i}d\mu(\frac id)=i^2\varphi(i)\\ \end{aligned}}i=1∑n​j=1∑n​ijgcd(i,j)​=k=1∑n​i=1∑n​j=1∑n​ijk[gcd(i,j)=k]=k=1∑n​k3i=1∑⌊kn​⌋​j=1∑⌊kn​⌋​ijd∣i,d∣j∑​μ(d)=k=1∑n​k3d=1∑⌊kn​⌋​d2μ(d)i=1∑⌊kdn​⌋​j=1∑⌊kdn​⌋​ij=k=1∑n​k3d=1∑⌊kn​⌋​d2μ(d)sum(⌊kdn​⌋)2......sum(n)=2n(n+1)​=T=1∑n​sum(⌊Tn​⌋)2k∣T∑​k3(kT​)2μ(kT​)......令T=kd=i=1∑n​sum(⌊in​⌋)2i2d∣i∑​dμ(di​)=i=1∑n​sum(⌊in​⌋)2f(i)......令f(i)=i2d∣i∑​dμ(di​)=i2φ(i)​
也就是说我们只要能求f(i)=i2φ(i)\mathbf{f(i)=i^2\varphi(i)}f(i)=i2φ(i)的前缀和就能分块做出本题了,设S(n)=∑i=1ni2φ(i)\mathbf{S(n)=\sum_{i=1}^ni^2\varphi(i)}S(n)=∑i=1n​i2φ(i),我们注意到f∗id2=id3\mathbf{f*id_2=id_3}f∗id2​=id3​,其中idk(n)=nk\mathbf{id_k(n)=n^k}idk​(n)=nk。于是我们可以得到杜教筛的式子:S(n)=∑i=1nid3(i)−∑i=2ni2S(⌊ni⌋)\mathbf{S(n)=\sum_{i=1}^nid_3(i)-\sum_{i=2}^ni^2S(\lfloor \frac ni\rfloor)}S(n)=∑i=1n​id3​(i)−∑i=2n​i2S(⌊in​⌋),然后就是套路的做法即可。
然后有一些可以优化的地方,我们可以预处理出id2,id3\mathbf{id_2,id_3}id2​,id3​,避免重复计算浪费时间,当然也可以记忆化(下面的代码用的就是记忆化),然后注意到模数不超过1.1e9\mathbf{1.1e9}1.1e9,故所有除n外的变量都用int\mathbf{int}int类型即可,时间会更快一些,然后杜教筛的记忆化工作这里不采用unordered_map,直接对2⌊n⌋\mathbf{2\lfloor\sqrt n\rfloor}2⌊n​⌋个值做映射即可,对于x\mathbf{x}x而言,若x≤⌊n⌋\mathbf{x\le\lfloor\sqrt n\rfloor}x≤⌊n​⌋我们直接用x\mathbf{x}x作为离散化编号,否则用⌊n⌋+⌊nx⌋\mathbf{\lfloor \sqrt n\rfloor+\lfloor\frac nx\rfloor}⌊n​⌋+⌊xn​⌋作为离散化编号,这样可以做到真正地O(1)\mathbf{O(1)}O(1)记忆化。
通过以上优化可以跑出洛谷第一的好成绩。

代码:

int p,inv4,inv6,prim[maxn],tot,f[maxn],rec[maxm],limt,m2[maxm],m3[maxm];
ll n;
int id(ll x){return x<=limt?x:limt+n/x;
}
int sm1(ll n){n%=p;return (n*(n+1)>>1)%p;
}
int sm2(ll n){int idd=id(n);if(m2[idd])return m2[idd];n%=p;return m2[idd]=n*(n+1)%p*(2*n+1)%p*inv6%p;
}
int sm3(ll n){int idd=id(n);if(m3[idd])return m3[idd];n%=p;return m3[idd]=n*n%p*(n+1)%p*(n+1)%p*inv4%p;
}
void init(int n){bitset<maxn>flag;f[1]=1;FOR(i,2,n+1){if(!flag[i])prim[tot++]=i,f[i]=i-1;for(register int j = 0;j<tot && i*prim[j]<=n;++j){flag[i*prim[j]]=1;if(i%prim[j]==0){f[i*prim[j]]=1ll*f[i]*prim[j]%p;break;}f[i*prim[j]]=1ll*f[i]*(prim[j]-1)%p;}}FOR(i,1,n+1)f[i]=(f[i-1]+1ll*f[i]*i%p*i%p)%p;
}
int S(ll n){if(n<maxn)return f[n];register int idd=id(n);if(rec[idd])return rec[idd];register int ans=sm3(n);register ll i =2,j;while(i<=n){j=n/(n/i);ans=(ans-1ll*S(n/i)*(sm2(j)-sm2(i-1))%p)%p;i=j+1;}return rec[idd]=ans;
}
int main(){rd(&p,&n);limt=ceil(sqrt(n));inv4=qpow(4,p-2,p);inv6=qpow(6,p-2,p);init(min(n,maxn-1ll));register int ans=0,sm;register ll i =1,j;while(i<=n){j=n/(n/i);sm=sm1(n/i);ans=(ans+1ll*(S(j)-S(i-1))*sm%p*sm%p)%p;i=j+1;}ans=(ans%p+p)%p;wrn(ans);
}

(2).min_25筛

[1].原理介绍

min_25筛用于求积性函数前缀和,不过对积性函数f(n)\mathbf{f(n)}f(n)有两个限制,一是f(p),(p为质数)\mathbf{f(p),(p为质数)}f(p),(p为质数)的表达式是一个多项式二是f(pk)\mathbf{f(p^k)}f(pk)能够快速求解。

现在假设p1,p2,...,pk\mathbf{p_1,p_2,...,p_k}p1​,p2​,...,pk​代表所有小于等于n\mathbf{n}n的素数从小到大排起来的一个序列,再设S(n,j)=∑i=2n[minp(i)>=pj]f(i)\mathbf{S(n,j)=\sum_{i=2}^n[minp(i)>=p_j]f(i)}S(n,j)=∑i=2n​[minp(i)>=pj​]f(i),其中minp(i)\mathbf{minp(i)}minp(i)表示i的最小质因子。那么显然有∑i=1f(i)=S(n,1)+f(1)\mathbf{\sum_{i=1}f(i)=S(n,1)+f(1)}∑i=1​f(i)=S(n,1)+f(1),于是我们只要能求出S(n,1)\mathbf{S(n,1)}S(n,1)就行了。

min_25筛给出了一个可行的想法就是把所有数对S(n,j)\mathbf{S(n,j)}S(n,j)的贡献分为两个部分,即合数和素数。我们先考虑素数对S(n,j)\mathbf{S(n,j)}S(n,j)的贡献,根据S(n,j)\mathbf{S(n,j)}S(n,j)的定义显然是∑i=1kf(pi)\mathbf{\sum_{i=1}^kf(p_i)}∑i=1k​f(pi​),不过由于n\mathbf{n}n一般非常大,相应地pk\mathbf{p_k}pk​也非常大,故我们是无法直接求出这一部分的,因此这里设g(n,j)=∑i=2n[minp(i)>j或i是质数]ic\mathbf{g(n,j)=\sum_{i=2}^n[minp(i)>j或i是质数]i^c}g(n,j)=∑i=2n​[minp(i)>j或i是质数]ic,这里的ic\mathbf{i^c}ic是f(i)\mathbf{f(i)}f(i)多项式的其中一项。那么显然有∑i=1kpic=g(n,k)\mathbf{\sum_{i=1}^kp_i^c=g(n,k)}∑i=1k​pic​=g(n,k),注意到f(i)\mathbf{f(i)}f(i)是多项式,我们可以对它的每一项建立一个g\mathbf{g}g函数然后求出这一项的前缀和,然后加起来就能得到∑i=1kf(pi)\mathbf{\sum_{i=1}^kf(p_i)}∑i=1k​f(pi​)了,至于g(n,j)\mathbf{g(n,j)}g(n,j)怎么求下文说明。

再看看合数对S(n,j)\mathbf{S(n,j)}S(n,j)的贡献,我们需要枚举所有的合数,一种简单的枚举方式是直接从小到大一个一个枚举然后判断是不是合数,不过这样做效率极其低下,我们考虑直接枚举合数的所有质因子,而且是从最小质因子开始枚举。注意前面要求f(n)\mathbf{f(n)}f(n)是一个积性函数,故任何一个数的f\mathbf{f}f值可以被拆分为它的最小质因子的幂次的f\mathbf{f}f值和其剩余部分的f\mathbf{f}f值的乘积,因此对于S(n,j)\mathbf{S(n,j)}S(n,j)而言我们先枚举pa(a≥j)\mathbf{p_a(a\ge j)}pa​(a≥j)按从小到大的顺序,把它作为枚举的这个合数的最小质因子,然后枚举它的幂次e,e≥1\mathbf{e,e\ge 1}e,e≥1,这个部分对应的值为f(pae)\mathbf{f(p_a^e)}f(pae​),当然还有其它部分,其它部分还需要枚举,也是枚举最小质因子,不过可以肯定的是其它部分的最小质因子一定大于pa\mathbf{p_a}pa​,稍加思考容易发现它们的和一定是S(npae,a+1)\mathbf{S(\frac n{p_a^e},a+1)}S(pae​n​,a+1),当然如果我们发现npae<pa+1\mathbf{\frac n{p_a^e}<p_{a+1}}pae​n​<pa+1​就意味着没有必要再枚举pae\mathbf{p_a^e}pae​了,我们可以考虑枚举下一个pa+1\mathbf{p_{a+1}}pa+1​以及它的幂次,不过由于我们需要特别地计算pae\mathbf{p_a^e}pae​这个特殊地合数的贡献,故需要枚举的终止条件实际上是pae>n\mathbf{p_a^e> n}pae​>n,故我们可以写出关于S(n,j)\mathbf{S(n,j)}S(n,j)的合数部分的表达式为∑a≥j,n≥pa2∑e≥1,n≥paef(pae)([e>1]+S(npae,a+1))\mathbf{\sum_{a\ge j,n\ge p_a^2}\sum_{e\ge 1,n\ge p_a^e}f(p_a^e)([e>1]+S(\frac n{p_a^e},a+1))}∑a≥j,n≥pa2​​∑e≥1,n≥pae​​f(pae​)([e>1]+S(pae​n​,a+1)),注意这里面的[e>1]\mathbf{[e>1]}[e>1]算的是pae\mathbf{p_a^e}pae​这个合数的贡献,对于e=1\mathbf{e=1}e=1的情况已经算到质数那一部分去了。

不过合数部分的这个式子还能再优化一下,前面说到当npae<pa+1\mathbf{\frac n{p_a^e}<p_{a+1}}pae​n​<pa+1​其实就没必要枚举了,因为在这个条件下S(npae,a+1)\mathbf{S(\frac n{p_a^e},a+1)}S(pae​n​,a+1)一定为0了,只是考虑到要单独算pae\mathbf{p_a^e}pae​的贡献才将终止条件放宽。我们发现e=1\mathbf{e=1}e=1的时候在式子中的[e>1]\mathbf{[e>1]}[e>1]项其实不会产生贡献,故我们干脆写成f(pae+1)+f(pae)S(npae,a+1)\mathbf{f(p_a^{e+1})+f(p_a^e)S(\frac n{p_a^e},a+1)}f(pae+1​)+f(pae​)S(pae​n​,a+1)不就行了,不过这时候枚举终止条件仍然不能改成npae<pa+1\mathbf{\frac n{p_a^e}<p_{a+1}}pae​n​<pa+1​,但稍微弱化一下我们改成npae<pa\mathbf{\frac n{p_a^e}<p_a}pae​n​<pa​也不错,也能比最开始减少一点枚举量,这样终止条件可以写成pae+1>n\mathbf{p_a^{e+1}>n}pae+1​>n,相应地枚举的时候我们要求pae+1≤n\mathbf{p_a^{e+1}\le n}pae+1​≤n,这样就能得到∑a≥j,n≥pa2∑e≥1,n≥pae+1f(pae+1)+f(pae)S(npae,a+1)\mathbf{\sum_{a\ge j,n\ge p_a^2}\sum_{e\ge 1,n\ge p_a^{e+1}}f(p_a^{e+1})+f(p_a^{e})S(\frac n{p_a^e},a+1)}∑a≥j,n≥pa2​​∑e≥1,n≥pae+1​​f(pae+1​)+f(pae​)S(pae​n​,a+1),这样枚举量比原来还是少了许多,对算法有一定的优化效果。

这样结合质数部分的话我们就能得到S(n,j)\mathbf{S(n,j)}S(n,j)的表达式:
S(n,j)=g(n,k)+∑a≥j,n≥pa2∑e≥1,n≥pae+1f(pae+1)+f(pae)S(npae,a+1)\mathbf{S(n,j)=g(n,k)+\sum_{a\ge j,n\ge p_a^2}\sum_{e\ge 1,n\ge p_a^{e+1}}f(p_a^{e+1})+f(p_a^{e})S(\frac n{p_a^e},a+1)}S(n,j)=g(n,k)+a≥j,n≥pa2​∑​e≥1,n≥pae+1​∑​f(pae+1​)+f(pae​)S(pae​n​,a+1)
这里的g(n,k)\mathbf{g(n,k)}g(n,k)是算出f(n)\mathbf{f(n)}f(n)这个多项式每一项的结果后合并的总结果。注意到pa≤sqrt(n)\mathbf{p_a\le sqrt(n)}pa​≤sqrt(n),故枚举的质数不会很多。

然后现在我们考虑如何求g(n,j)=∑i=2n[minp(i)>j或i是质数]ic\mathbf{g(n,j)=\sum_{i=2}^n[minp(i)>j或i是质数]i^c}g(n,j)=∑i=2n​[minp(i)>j或i是质数]ic,方便起见设h(i)=ic\mathbf{h(i)=i^c}h(i)=ic,显然h(n)\mathbf{h(n)}h(n)是一个完全积性函数。然后我们考察由g(n,j−1)\mathbf{g(n,j-1)}g(n,j−1)到g(n,j)\mathbf{g(n,j)}g(n,j)的变化,显然g(n,j)\mathbf{g(n,j)}g(n,j)只是比g(n,j−1)\mathbf{g(n,j-1)}g(n,j−1)少了那些最小质因子为pj\mathbf{p_j}pj​的合数的贡献,这些合数除去一个pj\mathbf{p_j}pj​因子后的剩余部分的贡献显然为g(npj,j−1)\mathbf{g(\frac n{p_j},j-1)}g(pj​n​,j−1),不过这个里面还带有小于pj\mathbf{p_j}pj​的质因子的和,故我们还需要减去一个g(pj−1,j−1)\mathbf{g(p_j-1,j-1)}g(pj​−1,j−1)。故我们可以写成g(n,j)=g(n,j−1)−h(pj)[g(npj,j−1)−g(pj−1,j−1)]\mathbf{g(n,j)=g(n,j-1)-h(p_j)[g(\frac n{p_j},j-1)-g(p_j-1,j-1)]}g(n,j)=g(n,j−1)−h(pj​)[g(pj​n​,j−1)−g(pj​−1,j−1)]。
不过这样递推下去好像复杂度会爆炸,我们看看pj2>n\mathbf{p_j^2>n}pj2​>n的情况,这时候会发现在[2,n]\mathbf{[2,n]}[2,n]的范围内没有数满足minp>pj\mathbf{minp>p_j}minp>pj​,故此时我们有g(n,j)=g(n,j−1),ifpj2>n\mathbf{g(n,j)=g(n,j-1),if\quad p_j^2>n}g(n,j)=g(n,j−1),ifpj2​>n,也正是由于这个原因我们可以把S(n,j)\mathbf{S(n,j)}S(n,j)表达式中的g(n,k)\mathbf{g(n,k)}g(n,k)的k\mathbf{k}k改成更小的一个数t\mathbf{t}t使得pt2≤n\mathbf{p_t^2\le n}pt2​≤n。

综上我们能够得到:
g(n,j)={g(n,j−1),ifpj2>ng(n,j−1)−h(pj)[g(npj,j−1)−g(pj−1,j−1)],ifpj2≤n\mathbf{g(n,j)=\begin{cases} g(n,j-1),&if\quad p_j^2>n\\ g(n,j-1)-h(p_j)[g(\frac n{p_j},j-1)-g(p_j-1,j-1)],&if\quad p_j^2\le n \end{cases}}g(n,j)={g(n,j−1),g(n,j−1)−h(pj​)[g(pj​n​,j−1)−g(pj​−1,j−1)],​ifpj2​>nifpj2​≤n​
S(n,j)=g(n,t)+∑a≥j,n≥pa2∑e≥1,n≥pae+1f(pae+1)+f(pae)S(npae,a+1),pt2≤n\mathbf{S(n,j)=g(n,t)+\sum_{a\ge j,n\ge p_a^2}\sum_{e\ge 1,n\ge p_a^{e+1}}f(p_a^{e+1})+f(p_a^{e})S(\frac n{p_a^e},a+1),p_t^2\le n}S(n,j)=g(n,t)+∑a≥j,n≥pa2​​∑e≥1,n≥pae+1​​f(pae+1​)+f(pae​)S(pae​n​,a+1),pt2​≤n

具体编码过程中我们不会开一个两维的数组取储存g(n,j)\mathbf{g(n,j)}g(n,j),注意到递推到n\mathbf{n}n并不需要小于n的所有的数,实际上只需要n2,n3...\mathbf{\frac n2,\frac n3...}2n​,3n​...这种形式的数,它们有2⌊n⌋\mathbf{2\lfloor \sqrt n\rfloor}2⌊n​⌋个,因此可以提前离散化,相当于给它们都重编号,然后在它们之间递推即可。而j\mathbf{j}j的话你可以理解为层,我们的目的是从第一层往更高层推,直到出现pj2>n\mathbf{p_j^2>n}pj2​>n为止,具体实现可参考习题中的代码。

然后对于S(n,j)\mathbf{S(n,j)}S(n,j)而言直接写个递归函数即可,而且经过证明不需要记忆化,复杂度最终是O(n34log(n))\mathbf{O(\frac{n^{\frac 34}}{log(n)})}O(log(n)n43​​)。

[2].习题

例题一
题目来源:LuoGuP5325 【模板】Min_25筛

题面:

题解:本题给出的积性函数满足f(pk)\mathbf{f(p^k)}f(pk)是一个多项式,即可以表示成f(x)=x2−x\mathbf{f(x)=x^2-x}f(x)=x2−x当x是质数的时候,于是设两个g\mathbf{g}g函数来分别算对应的项即可,注意初始化g1[n]=1+2+...+n,g2[n]=12+22+...+n2\mathbf{g_1[n]=1+2+...+n,g_2[n]=1^2+2^2+...+n^2}g1​[n]=1+2+...+n,g2​[n]=12+22+...+n2,然后对于g1\mathbf{g_1}g1​就利用公式g1[n][j]=g1[n][j−1]−prim[j]∗(g1[⌊nprim[j]⌋][j−1]−g1[prim[j]−1][j−1])\mathbf{g_1[n][j]=g_1[n][j-1]-prim[j]*(g_1[\lfloor \frac n{prim[j]}\rfloor][j-1]-g_1[prim[j]-1][j-1])}g1​[n][j]=g1​[n][j−1]−prim[j]∗(g1​[⌊prim[j]n​⌋][j−1]−g1​[prim[j]−1][j−1])递推即可,对于g2\mathbf{g_2}g2​则利用公式g2[n][j]=g2[n][j−1]−prim[j]2∗(g2[⌊nprim[j]⌋][j−1]−g2[prim[j]−1][j−1])\mathbf{g_2[n][j]=g_2[n][j-1]-prim[j]^2*(g_2[\lfloor \frac n{prim[j]}\rfloor][j-1]-g_2[prim[j]-1][j-1])}g2​[n][j]=g2​[n][j−1]−prim[j]2∗(g2​[⌊prim[j]n​⌋][j−1]−g2​[prim[j]−1][j−1])递推,然后我们在循环的时候枚举j\mathbf{j}j,故我们可以省略第二维,以g1\mathbf{g_1}g1​为例我们可以把递推式变成g1[n]−=prim[j]∗(g1[⌊nprim[j]⌋]−g1[prim[j]−1])\mathbf{g_1[n]-=prim[j]*(g_1[\lfloor \frac n{prim[j]}\rfloor]-g_1[prim[j]-1])}g1​[n]−=prim[j]∗(g1​[⌊prim[j]n​⌋]−g1​[prim[j]−1]),不过要注意取模的问题。然后注意在第二层循环的时候(即内层循环)我们需要通过更小的⌊nprim[j]⌋\mathbf{\lfloor \frac n{prim[j]}\rfloor}⌊prim[j]n​⌋向着n\mathbf{n}n递推才行,有点像背包,由于它是一层一层递推的关系,你得在得出更大的n的g1\mathbf{g_1}g1​值的时候保证更小的n对应的g1[n]\mathbf{g_1[n]}g1​[n]值还没有被覆盖,故内层循环递推的顺序得从大到小,此外在离散化的时候要注意离散化后的坐标的顺序关系。
根据公式g1[n][j]=g1[n][j−1],ifprim[j]2>n\mathbf{g_1[n][j]=g_1[n][j-1],if\quad prim[j]^2>n}g1​[n][j]=g1​[n][j−1],ifprim[j]2>n我们知道第一层循环只需要递推O(n)\mathbf{O(\sqrt n)}O(n​)层即可,然后内层循环也不一定是每次要循环O(n)\mathbf{O(\sqrt n)}O(n​)次,事实上我们从大到小枚举n,对于不满足prim[j]2≤n\mathbf{prim[j]^2\le n}prim[j]2≤n的n\mathbf{n}n我们可以直接退出内层循环,所以复杂度很小,有论文证明是O(n34log(n))\mathbf{O(\frac{n^{\frac 34}}{log(n)})}O(log(n)n43​​)。

最后是算S(n,0)\mathbf{S(n,0)}S(n,0),当然n你可以用离散化的坐标代替,下面给出的代码也是这么做的,根据上面的公式直接在函数里递归即可,不需要记忆化。

代码:

const int mod = 1e9+7;
ll n,num[maxn];
int limt,prim[maxn],flag[maxn],tot,id1[maxn],id2[maxn],m,g1[maxn],g2[maxn];int id(ll x){return x<=limt?id1[x]:id2[n/x];
}
void init(int n){FOR(i,2,n+1){if(!flag[i])prim[tot++]=i;for(register int j =0;j<tot&&prim[j]*i<=n;++j){flag[i*prim[j]]=1;if(i%prim[j]==0)break;}}
}
int S(int idd,int j){register ll pe,pee,n=num[idd];if(n<prim[j])return 0;register int ans=((g2[idd]-g1[idd])%mod-(g2[id(prim[j]-1)]-g1[id(prim[j]-1)])%mod)%mod,pem,peem;for(register int i = j;i<tot && 1ll*prim[i]*prim[i]<=n;++i){//min_25筛合数部分for(pe = prim[i],pee=pe*prim[i],peem=pee%mod,pem=pe%mod;pee<=n;pe*=prim[i],pee*=prim[i],peem=pee%mod,pem=pe%mod){ans=((ans+1ll*peem*(peem-1)%mod)%mod+1ll*pem*(pem-1)%mod*S(id(n/pe),i+1)%mod)%mod;}}return ans;
}
int main(){rd(&n);limt=sqrt(n);register ll i=1,j;register int x,inv6=qpow(6,mod-2,mod);while(i<=n){j=n/(n/i);num[m++]=n/i,x=num[m-1]%mod;//离散化 if(n/i<=limt)id1[n/i]=m-1;else id2[i]=m-1;g1[m-1]=(1ll*x*(x+1)>>1)%mod-1;//初始化g1,g1[n]=1+2+3+...+ng2[m-1]=1ll*x*(x+1)%mod*(2*x+1)%mod*inv6%mod-1;//初始化g2,g2[n]=1^2+2^2+...+n^2i=j+1;}init(limt+100);//线性筛处理处sqrt(n)以内的质数 FOR(j,0,tot){//第二维递推 for(register int i = 0;i<m && 1ll*prim[j]*prim[j]<=num[i];++i){//min_25筛质数部分第一维递推 g1[i]=(g1[i]-1ll*prim[j]*(g1[id(num[i]/prim[j])]-g1[id(prim[j]-1)])%mod)%mod; g2[i]=(g2[i]-1ll*prim[j]*prim[j]%mod*(g2[id(num[i]/prim[j])]-g2[id(prim[j]-1)])%mod)%mod;}}int ans=S(0,0)+1;ans=(ans%mod+mod)%mod;wrn(ans);
}

例题二
题目来源:LOJ#6053. 简单的函数

题面:

题解:由于f(p)=p−1+2[p=2]\mathbf{f(p)=p-1+2[p=2]}f(p)=p−1+2[p=2],我们可以先忽略掉2[p=2]\mathbf{2[p=2]}2[p=2]这一项,然后算出∑i=1kpi−1\mathbf{\sum_{i=1}^kp_i-1}∑i=1k​pi​−1,然后对g[i],i≥2\mathbf{g[i],i\ge 2}g[i],i≥2都加上一个2即可。然后S(n,j)\mathbf{S(n,j)}S(n,j)函数的递归写法也跟模板题差不多,只不过乘的时候需要乘上prim[i]xorc\mathbf{prim[i]\quad xor\quad c}prim[i]xorc,下面给出一份优化版本的参考代码。
代码:

ll n,num[maxn];
int limt,tot,prim[maxn],g1[maxn],g2[maxn],m,id1[maxn],id2[maxn];int id(ll x){return x<=limt?id1[x]:id2[n/x];
}
void init(int n){bitset<maxn>flag;FOR(i,2,n+1){if(!flag[i])prim[tot++]=i;for(register int j =0;j<tot && prim[j]*i<=n;++j){flag[i*prim[j]]=1;if(i%prim[j]==0)break;}}
}
int S(int idd,int j){register ll n=num[idd],pe,pee;if(n<prim[j])return 0;register int ct,ans=sub(g1[idd],g1[id(prim[j]-1)]);for(register int i = j;i<tot && 1ll*prim[i]*prim[i]<=n;++i)for(pe=prim[i],pee=1ll*prim[i]*prim[i],ct=1;pee<=n;pe=pee,pee*=prim[i],ct++){add(ans,sum(prim[i]^(ct+1),1ll*(prim[i]^ct)%mod*S(id(n/pe),i+1)%mod));}return ans;
}
int main(){rd(&n);limt=sqrt(n);init(limt+100);register ll i =1,j,x;while(i<=n){j=n/(num[m++]=n/i);x=num[m-1]%mod;if(num[m-1]<=limt)id1[num[m-1]]=m-1;else id2[j]=m-1;g1[m-1]=sub((1ll*x*(x+1)>>1)%mod,1);g2[m-1]=sub(x,1);i=j+1;}FOR(j,0,tot)for(register int i =0;i<m && 1ll*prim[j]*prim[j]<=num[i];++i){dec(g1[i],1ll*prim[j]*sub(g1[id(num[i]/prim[j])],g1[id(prim[j]-1)])%mod);dec(g2[i],sub(g2[id(num[i]/prim[j])],g2[id(prim[j]-1)]));} FOR(i,0,m-1)dec(g1[i],sub(g2[i],2));int ans=sum(S(0,0),1);wrn(ans);
}

(3).洲阁筛

鸽了。。。。一般min_25筛和杜教筛能够解决大部分问题,所以鸽了,有空再补吧

6.推式子综合技巧

这一小节主要总结反演过程中的一些技巧性变换,有些可能并不是很难,但是其思想却很重要;有些则技巧性特别强,不太容易想到。

  1. ∑i=1n∑j=1m[gcd(i,j)=d]=∑i=1⌊nd⌋∑j=1⌊md⌋[gcd(i,j)=1]\mathbf{\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=d]=\sum_{i=1}^{\lfloor \frac nd\rfloor}\sum_{j=1}^{\lfloor \frac md\rfloor}[gcd(i,j)=1]}∑i=1n​∑j=1m​[gcd(i,j)=d]=∑i=1⌊dn​⌋​∑j=1⌊dm​⌋​[gcd(i,j)=1]。
    证明:见第十部分4.(3).例题一种关于①的证明部分。

  2. [n=1]=∑d∣nμ(d)\mathbf{[n=1]=\sum_{d\mid n}\mu(d)}[n=1]=∑d∣n​μ(d)。
    证明:该式子本质就是μ∗I=ϵ\mathbf{\mu*I=\epsilon}μ∗I=ϵ,具体证明见第十部分3.(3).3。

  3. ∑i=1n∑j=1⌊ni⌋f(i)=∑i=1n∑j=1⌊ni⌋f(j)\mathbf{\sum_{i=1}^n\sum_{j=1}^{\lfloor \frac ni\rfloor}f(i)=\sum_{i=1}^n\sum_{j=1}^{\lfloor \frac ni\rfloor}f(j)}∑i=1n​∑j=1⌊in​⌋​f(i)=∑i=1n​∑j=1⌊in​⌋​f(j)。
    证明:
    ∑i=1n∑j=1⌊ni⌋f(i)=∑i=1n∑j=1,ij≤nf(i)=∑j=1,ij≤n∑i=1nf(i)=∑j=1n∑i=1,ij≤nf(i)=∑j=1n∑i=1⌊nj⌋f(i)=∑i=1n∑j=1⌊ni⌋f(j)\mathbf{\begin{aligned} \sum_{i=1}^n\sum_{j=1}^{\lfloor \frac ni\rfloor}f(i)&=\sum_{i=1}^n\sum_{j=1,ij\le n}f(i)\\ &=\sum_{j=1,ij\le n}\sum_{i=1}^nf(i)\\ &=\sum_{j=1}^{n}\sum_{i=1,ij\le n}f(i)\\ &=\sum_{j=1}^n\sum_{i=1}^{\lfloor \frac nj\rfloor}f(i)\\ &=\sum_{i=1}^n\sum_{j=1}^{\lfloor \frac ni\rfloor}f(j) \end{aligned}}i=1∑n​j=1∑⌊in​⌋​f(i)​=i=1∑n​j=1,ij≤n∑​f(i)=j=1,ij≤n∑​i=1∑n​f(i)=j=1∑n​i=1,ij≤n∑​f(i)=j=1∑n​i=1∑⌊jn​⌋​f(i)=i=1∑n​j=1∑⌊in​⌋​f(j)​

  4. ∑i=1n∑j=1⌊ni⌋f(ij)g(i)h(j)=∑T=1nf(T)∑d∣Tg(d)h(Td)\mathbf{\sum_{i=1}^n\sum_{j=1}^{\lfloor \frac ni\rfloor}f(ij)g(i)h(j)=\sum_{T=1}^nf(T)\sum_{d\mid T}g(d)h(\frac Td)}∑i=1n​∑j=1⌊in​⌋​f(ij)g(i)h(j)=∑T=1n​f(T)∑d∣T​g(d)h(dT​)。
    证明:经常使用的套路,将两个枚举量的乘积设为一个新的枚举量,在前面的题中也出现过,比如第十部分4.(3).例题三,可以参考那题的证明。

  5. gcd(n,m)=∑i∣n,i∣mφ(i)\mathbf{gcd(n,m)=\sum_{i\mid n,i\mid m}\varphi(i)}gcd(n,m)=∑i∣n,i∣m​φ(i)。
    证明:根据第十部分3.(3).5我们知道id=φ∗I\mathbf{id=\varphi*I}id=φ∗I,即n=∑i∣nφ(i)\mathbf{n=\sum_{i\mid n}\varphi(i)}n=∑i∣n​φ(i),于是有gcd(n,m)=∑i∣gcd(n,m)φ(i)\mathbf{gcd(n,m)=\sum_{i\mid gcd(n,m)}\varphi(i)}gcd(n,m)=∑i∣gcd(n,m)​φ(i),注意到一个基本的等价关系:i∣gcd(n,m)⇔i∣n且i∣m\mathbf{i\mid gcd(n,m)\Leftrightarrow i\mid n且i\mid m}i∣gcd(n,m)⇔i∣n且i∣m,因此易得:gcd(n,m)=∑i∣n,i∣mφ(i)\mathbf{gcd(n,m)=\sum_{i\mid n,i\mid m}\varphi(i)}gcd(n,m)=∑i∣n,i∣m​φ(i)。

  6. ∑i=1ni[gcd(i,n)=1]=[n=1]+nφ(n)2\mathbf{\sum_{i=1}^ni[gcd(i,n)=1]=\frac{[n=1]+n\varphi(n)}2}∑i=1n​i[gcd(i,n)=1]=2[n=1]+nφ(n)​。
    证明:这个式子在第四部分5.(4).3中被证明,不过当n=1\mathbf{n=1}n=1时需要特判,故需要加上[n=1]\mathbf{[n=1]}[n=1]这一项。

  7. φ(n)=∑i=1n[gcd(i,n)=1]\mathbf{\varphi(n)=\sum_{i=1}^n[gcd(i,n)=1]}φ(n)=∑i=1n​[gcd(i,n)=1]。
    证明:φ(n)\mathbf{\varphi(n)}φ(n)的定义式,没什么好说的,拉出来主要是想强调一下其重要性。

  8. 设n=p1e1p2e2...pkek\mathbf{n=p_1^{e_1}p_2^{e_2}...p_k^{e_k}}n=p1e1​​p2e2​​...pkek​​,则∑i=1n∑j=1m[lcm(i,j)=n]=∏i=1k(2ei+1)\mathbf{\sum_{i=1}^n\sum_{j=1}^m[lcm(i,j)=n]=\prod_{i=1}^k(2e_i+1)}∑i=1n​∑j=1m​[lcm(i,j)=n]=∏i=1k​(2ei​+1)。
    证明:设i=p1a1p2a2...pkak,j=p1b1p2b2...pkbk\mathbf{i=p_1^{a_1}p_2^{a_2}...p_k^{a_k},j=p_1^{b_1}p_2^{b_2}...p_k^{b_k}}i=p1a1​​p2a2​​...pkak​​,j=p1b1​​p2b2​​...pkbk​​根据第三部分(3).5我们知道只需要保证:max(ai,bi)=ei,∀i∈[1,k]\mathbf{max(a_i,b_i)=e_i,\forall i\in[1,k]}max(ai​,bi​)=ei​,∀i∈[1,k]即可,那么就成为一个组合计数问题了,显然对于任意i\mathbf{i}i而言ai,bi\mathbf{a_i,b_i}ai​,bi​的取值范围都在[0,e1]\mathbf{[0,e_1]}[0,e1​],且必须至少有一个刚好等于e1\mathbf{e_1}e1​,故种数有2e1+1\mathbf{2e_1+1}2e1​+1种,根据乘法原理我们可以得到总的种数为∏i=1k(2ei+1)\mathbf{\prod_{i=1}^k(2e_i+1)}∏i=1k​(2ei​+1)。

  9. d(ij)=∑x∣i∑y∣j[gcd(x,y)=1]\mathbf{d(ij)=\sum_{x\mid i}\sum_{y\mid j}[gcd(x,y)=1]}d(ij)=∑x∣i​∑y∣j​[gcd(x,y)=1]。
    证明:见第十部分4.(3).例题四。

  10. ∑d∣nμ(d)d=φ(n)n\mathbf{\sum_{d\mid n}\frac {\mu(d)}d=\frac {\varphi(n)}n}∑d∣n​dμ(d)​=nφ(n)​ 。
    证明:根据卷积的交换律有∑d∣nμ(d)d=∑d∣ndnμ(nd)=∑d∣ndμ(nd)n=φ(n)n\mathbf{\sum_{d\mid n}\frac{\mu(d)}d=\sum_{d\mid n}\frac dn\mu(\frac nd)=\frac{\sum_{d\mid n}d\mu(\frac nd)}n=\frac{\varphi(n)}n}∑d∣n​dμ(d)​=∑d∣n​nd​μ(dn​)=n∑d∣n​dμ(dn​)​=nφ(n)​,注意到其中用到的的μ∗id=φ\mathbf{\mu*id=\varphi}μ∗id=φ式子的证明在第十部分3.(3).4。

  11. μ(n)=∑d∣nμ(d)dφ(nd)\mathbf{\mu(n)=\sum_{d\mid n}\mu(d)d\varphi(\frac nd)}μ(n)=∑d∣n​μ(d)dφ(dn​)。
    证明:设f(n)=μ(n)n\mathbf{f(n)=\mu(n)n}f(n)=μ(n)n,我们要证明μ=f∗φ\mathbf{\mu=f*\varphi}μ=f∗φ,由于f∗id=∑d∣nμ(d)dnd=n∑d∣nμ(d)=n[n=1]=[n=1]=ϵ\mathbf{f*id=\sum_{d\mid n}\mu(d)d\frac nd=n\sum_{d\mid n}\mu(d)=n[n=1]=[n=1]=\epsilon}f∗id=∑d∣n​μ(d)ddn​=n∑d∣n​μ(d)=n[n=1]=[n=1]=ϵ,因此有f∗φ=f∗id∗μ=ϵ∗μ=μ\mathbf{f*\varphi=f*id*\mu=\epsilon *\mu=\mu}f∗φ=f∗id∗μ=ϵ∗μ=μ成立。其中用到的两个关系式:φ=id∗μ,ϵ∗μ=μ\mathbf{\varphi=id*\mu,\epsilon *\mu=\mu}φ=id∗μ,ϵ∗μ=μ的证明参考第十部分3.(3).4和第十部分3.(2).4。

  12. ∑i=1n[σ(i)%2=1]=⌊n⌋+⌊n2⌋\mathbf{\sum_{i=1}^n[\sigma(i)\%2=1]=\lfloor \sqrt n\rfloor+\lfloor \sqrt{\frac n2}\rfloor}∑i=1n​[σ(i)%2=1]=⌊n​⌋+⌊2n​​⌋。
    证明:这个式子就是让计算n\mathbf{n}n以内有多少个数的因数和为奇数,设x=p1a1p2a2...pkak\mathbf{x=p_1^{a_1}p_2^{a_2}...p_k^{a_k}}x=p1a1​​p2a2​​...pkak​​,根据公式σ(x)=(1+p11+p12+...+p1a1)(1+p21+p22+...+p2a2)...((1+pk1+pk2+...+pkak))\mathbf{\sigma(x)=(1+p_1^1+p_1^2+...+p_1^{a_1})(1+p_2^1+p_2^2+...+p_2^{a_2})...((1+p_k^1+p_k^2+...+p_k^{a_k}))}σ(x)=(1+p11​+p12​+...+p1a1​​)(1+p21​+p22​+...+p2a2​​)...((1+pk1​+pk2​+...+pkak​​))(证明见第十部分2.(4).[3])我们知道σ(x)\mathbf{\sigma(x)}σ(x)为奇数当且仅当∀i∈[1,k],(1+pi1+pi2+...+piai)\mathbf{\forall i\in[1,k],(1+p_i^1+p_i^2+...+p_i^{a_i})}∀i∈[1,k],(1+pi1​+pi2​+...+piai​​)为奇数,这里分两种情况考虑,当pi=2\mathbf{p_i=2}pi​=2,那么∀i∈[1,k],(1+pi1+pi2+...+piai)\mathbf{\forall i\in[1,k],(1+p_i^1+p_i^2+...+p_i^{a_i})}∀i∈[1,k],(1+pi1​+pi2​+...+piai​​)一定为奇数;当pi≠2\mathbf{p_i\ne 2}pi​​=2,则pi\mathbf{p_i}pi​一定是一个奇质数,因此当且仅当ai%2=0\mathbf{a_i\%2=0}ai​%2=0(即ai\mathbf{a_i}ai​是偶数)的时候满足(1+pi1+pi2+...+piai)\mathbf{(1+p_i^1+p_i^2+...+p_i^{a_i})}(1+pi1​+pi2​+...+piai​​)是偶数。也就是说如果我们除去x\mathbf{x}x的所有2因子后,满足条件的x一定是一个平方数(因为其它奇素数的幂次都是偶数次),而2的幂次无非是奇偶两种,故满足条件的x的形式要么是一个平方数要么除以2以后是个平方数。
    综上我们考虑n\mathbf{n}n以内有多少个数满足平方数和除以2是平方数的条件。先看平方数有多少个,由于x2≤n⇒x≤n⇒x≤⌊n⌋\mathbf{x^2\le n\Rightarrow x\le \sqrt n\Rightarrow x\le \lfloor \sqrt n\rfloor}x2≤n⇒x≤n​⇒x≤⌊n​⌋,因此x有⌊n⌋\mathbf{\lfloor \sqrt n\rfloor}⌊n​⌋个,从而符合条件的平方数有⌊n⌋\mathbf{\lfloor \sqrt n\rfloor}⌊n​⌋个。那么满足除以2是平方数的数有多少个呢?我们考虑这个数的形式为2x2\mathbf{2x^2}2x2,然后看x有多少个,显然x满足2x2≤n⇒x≤n2⇒x≤⌊n2⌋\mathbf{2x^2\le n\Rightarrow x\le \sqrt {\frac n2}\Rightarrow x\le\lfloor \sqrt{\frac n2}\rfloor}2x2≤n⇒x≤2n​​⇒x≤⌊2n​​⌋,故有⌊n2⌋\mathbf{\lfloor \sqrt{\frac n2}\rfloor}⌊2n​​⌋个除以2是平方数的数。我们看这两部分显然是没有任何交集的,故满足因数和为奇数的数的数目就是这两部分的总和,也就是⌊n⌋+⌊n2⌋\mathbf{\lfloor \sqrt n\rfloor +\lfloor\sqrt{\frac n2}\rfloor}⌊n​⌋+⌊2n​​⌋。
    ps:如果要算因数和为偶数的数的个数的话用n减一下这个式子即可。

  13. 设w(n)\mathbf{w(n)}w(n)为n的质因子个数,特别地w(1)=0\mathbf{w(1)=0}w(1)=0,则d(n2)=∑d∣n2w(d)\mathbf{d(n^2)=\sum_{d\mid n}2^{w(d)}}d(n2)=∑d∣n​2w(d)。
    证明:设n=p1a1p2a2...pkak\mathbf{n=p_1^{a_1}p_2^{a_2}...p_k^{a_k}}n=p1a1​​p2a2​​...pkak​​,于是有n2=p12a1p22a2...pk2ak\mathbf{n^2=p_1^{2a_1}p_2^{2a_2}...p_k^{2a_k}}n2=p12a1​​p22a2​​...pk2ak​​,根据d(n2)\mathbf{d(n^2)}d(n2)的实际意义我们需要找出n2\mathbf{n^2}n2所有质因子幂次组合的种数,我们可以这样组合:先从n\mathbf{n}n中选出一些因子出来,假设这个因子为d(d>1)(d=1的时候显然只有一种组合方式),考虑其质因数分解为d=pc1b1pc2b2...pck′bk′,(∀i∈[1,k′],1≤bi≤aci)\mathbf{d=p_{c_1}^{b_1}p_{c_2}^{b_2}...p_{c_{k'}}^{b_{k'}},(\forall i\in[1,k'],1\le b_i\le a_{c_i})}d=pc1​b1​​pc2​b2​​...pck′​bk′​​,(∀i∈[1,k′],1≤bi​≤aci​​),由于我们要组合出n2\mathbf{n^2}n2的因子,我们可以考虑对每个bi\mathbf{b_i}bi​提供两种选择:要么维持原样,要么加上一个aci\mathbf{a_{c_i}}aci​​,这样的话d\mathbf{d}d会变成d′\mathbf{d'}d′,而且有2w(d)\mathbf{2^{w(d)}}2w(d)种变法,且这些d′\mathbf{d'}d′能够保证互不相同。稍加思考容易发现通过这种组合方式我们能够取遍所有的n2\mathbf{n^2}n2的因数,而且不会重复,故满足d(n2)=∑d∣n2w(d)\mathbf{d(n^2)=\sum_{d\mid n}2^{w(d)}}d(n2)=∑d∣n​2w(d)。

  14. 设w(n)\mathbf{w(n)}w(n)为n的质因子个数,则2w(n)=∑d∣n∣μ(d)∣\mathbf{2^{w(n)}=\sum_{d\mid n}|\mu(d)|}2w(n)=∑d∣n​∣μ(d)∣。
    证明:设n=p1a1p2a2...pkak\mathbf{n=p_1^{a_1}p_2^{a_2}...p_k^{a_k}}n=p1a1​​p2a2​​...pkak​​,根据μ\mathbf{\mu}μ的定义我们知道∑d∣n∣μ(d)∣=∑d∣p1p2...pk∣μ(d)∣\mathbf{\sum_{d\mid n}|\mu(d)|=\sum_{d\mid p_1p_2...p_k}|\mu(d)|}∑d∣n​∣μ(d)∣=∑d∣p1​p2​...pk​​∣μ(d)∣,这个式子的意义就是从p1,p2,...,pk\mathbf{p_1,p_2,...,p_k}p1​,p2​,...,pk​中选若干(可以一个都不选)个数出来有多少种选法,显然有2数的个数\mathbf{2^{数的个数}}2数的个数种选法,而w(n)\mathbf{w(n)}w(n)恰好表示质因子个数,故有2w(n)=∑d∣n∣μ(d)∣\mathbf{2^{w(n)}=\sum_{d\mid n}|\mu(d)|}2w(n)=∑d∣n​∣μ(d)∣。

  15. n以内无平方因子数的个数为∑i=1⌊n⌋μ(i)⌊ni2⌋\mathbf{\sum_{i=1}^{\lfloor \sqrt n\rfloor}\mu(i)\lfloor \frac{n}{i^2}\rfloor}∑i=1⌊n​⌋​μ(i)⌊i2n​⌋。
    证明:设p1,p2,...,pk\mathbf{p_1,p_2,...,p_k}p1​,p2​,...,pk​表示⌊n⌋\mathbf{\lfloor \sqrt n\rfloor}⌊n​⌋以内的所有质数(从小到大排列),我们要计算n以内无平方因子的数的个数,根据容斥原理,最开始有n个数,我们先从中筛除掉含有p12\mathbf{p_1^2}p12​因子的所有数,这些数有⌊np12⌋\mathbf{\lfloor \frac n{p_1^2}\rfloor}⌊p12​n​⌋个,然后筛除掉含有p22\mathbf{p_2^2}p22​因子的所有数,这些数有⌊np22⌋\mathbf{\lfloor \frac n{p_2^2}\rfloor}⌊p22​n​⌋个…以此类推,显然当pi2>n\mathbf{p_i^2>n}pi2​>n的时候就不需要筛了,故只需要筛到pk\mathbf{p_k}pk​,我们可以得到筛除完剩下的值为n−∑i=1k⌊npi2⌋\mathbf{n-\sum_{i=1}^k\lfloor \frac n{p_i^2}\rfloor}n−∑i=1k​⌊pi2​n​⌋,然后由于多筛了,比如对于含有p12p22\mathbf{p_1^2p_2^2}p12​p22​因子的数被p12和p22\mathbf{p_1^2和p_2^2}p12​和p22​各筛了一次,我们需要加回来,于是得到了n−∑i=1k⌊npi2⌋+∑1≤i<j≤k⌊n(pipj)2⌋\mathbf{n-\sum_{i=1}^k\lfloor \frac n{p_i^2}\rfloor+\sum_{1\le i<j\le k}\lfloor \frac n{(p_ip_j)^2}\rfloor}n−∑i=1k​⌊pi2​n​⌋+∑1≤i<j≤k​⌊(pi​pj​)2n​⌋,然后对于同时含有三个质数平方因子的数又被多加了,我们需要加回去…以此类推,我们容易发现当筛奇数个平方因子的时候式子中是减号,偶数个平方因子的时候是加号,并且平方因子开根号后没有平方因子,这恰好与莫比乌斯函数相同,我们可以表示为∑dμ(d)⌊nd2⌋\mathbf{\sum_d\mu(d)\lfloor\frac n{d^2}\rfloor}∑d​μ(d)⌊d2n​⌋,显然当d\mathbf{d}d含有平方因子时μ(d)\mathbf{\mu(d)}μ(d)为0,故这些数不会被算进去,又由于d≤⌊n⌋\mathbf{d\le \lfloor \sqrt n\rfloor}d≤⌊n​⌋,故我们可以写成∑d=1⌊n⌋μ(d)⌊nd2⌋\mathbf{\sum_{d=1}^{\lfloor\sqrt n\rfloor}\mu(d)\lfloor\frac n{d^2}\rfloor}∑d=1⌊n​⌋​μ(d)⌊d2n​⌋。

  16. 完全平方数或除以2为完全平方数的数的因数个数为奇数。
    证明:见本节第12条。

  17. ∑i=1n1i=In(n)+12n+r\mathbf{\sum_{i=1}^n\frac 1i=In(n)+\frac 1{2n}+r}∑i=1n​i1​=In(n)+2n1​+r,其中r为欧拉常数0.57721566490153286060651209\mathbf{0.57721566490153286060651209}0.57721566490153286060651209,n越大近似度越高(至少大于10000,不过要根据题目精度而定,可以打个表看n多大合理)。
    证明:较复杂,需要用到微积分相关知识,如果感兴趣可参考这里。

  18. ∑i=1n∑j=1n[gcd(i,j)=d]=2∑i=2⌊nd⌋φ(i)+1\mathbf{\sum_{i=1}^n\sum_{j=1}^n[gcd(i,j)=d]=2\sum_{i=2}^{\lfloor \frac nd\rfloor}\varphi(i)+1}∑i=1n​∑j=1n​[gcd(i,j)=d]=2∑i=2⌊dn​⌋​φ(i)+1。
    证明:∑i=1n∑j=1n[gcd(i,j)=d]=∑i=1⌊nd⌋∑j=1⌊nd⌋[gcd(i,j)=1]=∑i=2⌊nd⌋∑j=1i−1[gcd(i,j)=1]+∑i=1j−1∑j=2⌊nd⌋[gcd(i,j)=1]+∑i=1⌊nd⌋[gcd(i,i)=1]=2(∑i=2⌊nd⌋∑j=1i−1[gcd(i,j)]=1])+1=2∑i=2⌊nd⌋φ(i)+1\begin{aligned}\sum_{i=1}^n\sum_{j=1}^n[gcd(i,j)=d]&=\sum_{i=1}^{\lfloor \frac nd\rfloor}\sum_{j=1}^{\lfloor \frac nd\rfloor}[gcd(i,j)=1]\\&=\sum_{i=2}^{\lfloor \frac nd\rfloor}\sum_{j=1}^{i-1}[gcd(i,j)=1]+\sum_{i=1}^{j-1}\sum_{j=2}^{\lfloor \frac nd\rfloor}[gcd(i,j)=1]+\sum_{i=1}^{\lfloor \frac nd\rfloor}[gcd(i,i)=1]\\&=2(\sum_{i=2}^{\lfloor \frac nd\rfloor}\sum_{j=1}^{i-1}[gcd(i,j)]=1])+1\\&=2\sum_{i=2}^{\lfloor \frac nd\rfloor}\varphi(i)+1\end{aligned}i=1∑n​j=1∑n​[gcd(i,j)=d]​=i=1∑⌊dn​⌋​j=1∑⌊dn​⌋​[gcd(i,j)=1]=i=2∑⌊dn​⌋​j=1∑i−1​[gcd(i,j)=1]+i=1∑j−1​j=2∑⌊dn​⌋​[gcd(i,j)=1]+i=1∑⌊dn​⌋​[gcd(i,i)=1]=2(i=2∑⌊dn​⌋​j=1∑i−1​[gcd(i,j)]=1])+1=2i=2∑⌊dn​⌋​φ(i)+1​

总结

本文主要讲述了acm中关于数论的常见应用,以知识点为主,在知识点的基础上提供简单的题目作为练习,更重要的是对整个acm中数论体系的框架有更加清晰的认识,也便于作者日后复习。
注意本文并不完全面向零基础,一些比较简单的算法文中并没有提及或者解释比较粗暴简略,大家如果还有不懂的地方建议去网上查阅,而对于更进阶地数论知识本文也不涉及(比如说关于原根、阶更深层次的性质和联系),再进一步就深入数学专业的领域了,如果有兴趣地话可以推荐买一本具体数学(不止数论)来研究研究,或者数学专业的数论教材也是非常不错的资料。

本文还会更新(不过可能会鸽一段时间),欢迎大佬指出文章中的错误…

acm-基础数论学习笔记(下)相关推荐

  1. 鸟叔linux私房菜基础篇简体,鸟叔的Linux私房菜基础篇-学习笔记(一)

    鸟叔的Linux私房菜基础篇-学习笔记(一) 开机进入命令行模式: ctrl+alt+[F1-F6]的任意键进入命令行编辑界面 ctrl+alt+F7进入图形界面模式 开始下达指令 [dmtsai@s ...

  2. Python基础知识学习笔记——Matplotlib绘图

    Python基础知识学习笔记--Matplotlib绘图 整理python笔记,以防忘记 文章目录 Python基础知识学习笔记--Matplotlib绘图 一.绘图和可视化 1.导入模块 2.一个简 ...

  3. python基础知识学习笔记(1)

    python 基础知识学习笔记(1) 总结一下Python基础知识,以防忘记. 文章目录 python 基础知识学习笔记(1) 一.起步 1.python安装与编译环境 二.变量和简单数据类型 三.列 ...

  4. linux基础命令学习笔记(二)

    linux基础命令学习笔记(二) 1.kill :终止进程  kill pid (唯一标示一个进程) kill -9  强制终止  kill -15 命令未结束不能终止 # ps aux 查看所有进程 ...

  5. 【基础】基础算法学习笔记(状态空间)

    基础算法学习笔记(状态空间) 一.状态空间 1.定义(什么是状态空间):一个实际问题的各种可能情况构成的集合.(解释:为什么需要算法来和程序来处理问题?如果一道题可以手算得到答案,换句话说就是存在通过 ...

  6. Python基础知识学习笔记(一)

    Python基础知识学习笔记(一) 文章目录 Python基础知识学习笔记(一) (一) 认识python 1.注释 2.变量及类型 3.关键字(标识符) (1)什么是关键字? (2)查看关键字 (3 ...

  7. opencv-python基础知识学习笔记

    opencv-python基础知识学习笔记 原博地址:https://www.cnblogs.com/silence-cho/p/10926248.html 目录: opencv-python基础知识 ...

  8. 图像基础知识学习笔记

    图像基础知识学习笔记 文章目录 图像基础知识学习笔记 前言 一.图像基础知识相关笔记 1.光学系统影响图像的结构主要包括什么? 2.常见噪声都有什么,其分类,及特点? 3.光圈,快门,景深? 4. I ...

  9. K8s基础知识学习笔记及部分源码剖析

    K8s基础知识学习笔记及部分源码剖析 在学习b站黑马k8s视频资料的基础上,查阅了配套基础知识笔记和源码剖析,仅作个人学习和回顾使用. 参考资料: 概念 | Kubernetes 四层.七层负载均衡的 ...

  10. P2P网络基础(学习笔记)

    P2P网络基础(学习笔记) 基本概述 P2P与C/S架构 P2P网络的特点 P2P网络的主要功能 P2P网络的分类 集中式 全分布式非结构化 全分布式结构化 混合式 比特币网络 P2P网络的应用 基本 ...

最新文章

  1. 数据库中什么是主键,什么是外键?
  2. 最新!第二轮“双一流”名单即将公布?8所高校官宣新增学科!
  3. 也许你需要点实用的-Web前端笔试题
  4. Erlang注册进程名称-tut16.erl
  5. OpenStack发布Ussuri版本 实现智能开源基础设施的自动化
  6. 新建一个express工程,node app无反应
  7. rk3128平台Android7.1调试USB接口wifi总结
  8. mysql基础之mariadb集群主从架构
  9. android 广播的权限,Android Broadcast 和 BroadcastReceiver的权限限制方式
  10. 关于TP模板的目录设置和渲染问题
  11. c语言运算符大全极其意义,C语言运算符大全
  12. 2022年安全员-A证操作证考试题模拟考试平台操作
  13. (由Active Desktop保存在桌面引起)桌面图标蓝底
  14. AngularJS 的 IE 兼容性
  15. favicon.ico无法访问
  16. iPhone中通过ics来添加农历与天气预报
  17. Transformer-Bert 学习笔记(一)
  18. java接口汽车品牌,88_熟练掌握ES Java API_对汽车品牌进行全文检索、精准查询和前缀搜索...
  19. 一打卡作弊软件被指破坏钉钉系统:CEO 被判 5 年 6 个月
  20. linux将时钟放在桌面上的,小技巧:Linux个性化面版时钟显示

热门文章

  1. 北斗导航 | EagleEye2000:国产激光雷达走进测绘世界
  2. 使用 Moment.js 吧时间戳生成格式化时间
  3. 电脑取消撤销快捷键是什么_都知道“撤消”快捷键是Ctrl Z,那“反撤消”是什么呢?...
  4. win10 文件系统错误-2147416359
  5. php实现电脑自动关机,如何设置定时关电脑?三种方法教你设置电脑自动关机
  6. Excel单元格内换行(包括空行)for Mac
  7. 调研报告之——可见光通信与可见光定位
  8. Linux基础学习笔记(持续更新)
  9. 超级计算机排名太湖之光,发布超级计算机排名,中国“神威太湖之光”荣登榜首(印刷版)...
  10. try的动词用法_try的用法