数论筛法小结

(Author:MuYC)

目录:

1 线性筛积性函数
1.1 积性函数的定义
1.2 常见的积性函数
1.3 函数积性分析
1.4 线性筛辅助筛积性函数数值
题目选讲
Bzoj P4804 欧拉心算

2 亚线性算法筛积性函数
2.1 介绍:
2.2 杜教筛
2.3 应用范围
2.4 前置知识
2.5 杜教筛使用方法
数论好题

(1) 线性筛积性函数

(1.1) 积性函数的定义

如果一个数论函数 (f(x)) ,满足如下关系,则乘函数 (f) 为积性函数:

(forall x perp y:f(xy) = f(x) imes f(y))

然后进一步定义 完全积性函数

如果一个数论函数 (f(x)) ,满足如下关系,则乘函数 (f)完全积性函数

(forall x,y: f(xy) = f(x) imes f(y))

(1.2) 常见的积性函数

  • 莫比乌斯函数 (mu(x) = egin{cases} 1 (x = 1) \ 0 (x含有平方因子) \ (-1)^k (k 为 x 的本质不同质因子数量)end{cases})

  • 欧拉函数,记作 $varphi(x) = $ 小于等于 (x) 的且与 (x) 互质的数的数量

  • 约数个数函数 (d(x) = displaystyle sum_{d | x} 1)

  • 约数和函数 (sigma_k = displaystyle sum_{d | x} d^k)。特别的,由定义可知,(d(x) = sigma displaystyle_0(x)),同时,下面我们只讨论 (k = 1) 的情况。

(1.3) 函数积性分析

  • 关于 (mu(x))

    如果 (x perp y),那么 (mu(y) = -mu(x)),根据定义可以得到。

  • 关于 (varphi(x):)

    倘若 (x) 质因数分解之后, (x = displaystyle ∏_{i = 1}^{i = k} p_i^{a_i})

    那么根据 (varphi(x)) 的求法可以得到 (varphi(x) = x imes ∏_{i = 1}^{i = k} frac{p_i - 1}{p_i})

    假若现在有 (x perp y),那么 (x,y) 没有公共质因子,根据上面的计算式不难得到 (varphi(xy) = varphi(x) imes varphi(y))

  • 关于 (d(x):)

    倘若 (x) 质因数分解之后, (x = displaystyle ∏_{i = 1}^{i = k} p_i^{a_i})

    (d(x) = displaystyle sum_{d | x} 1 = ∏_{i = 1}^{i = k} (a_i + 1))

    还是根据 (x perp y) 没有公共质因子可以得到, (d(xy) = d(x) imes d(y))

  • 关于 (sigma_k(x))

    (x) 的质因数分解形式还是同上,就不写出来了

    (sigma_1(x) = ∏_{i = 1}^{i = k} (1 + p_i^1 +p_i^2 + ... + p_i^{a_i}))

    关于这个式子的可以通过组合意义(乘法原理)得到。

    同样的,因为 (x perp y) 时,它们没有共同的质因子,因此可以得到 (sigma_1(xy) = sigma_1(x) imes sigma(y))

(1.4) 线性筛辅助筛积性函数数值

线性筛基本写法不用讲了。下面记 (P) 为质数集合,(P_i) 表示从小到大数的第 (i) 个质数。

先放一段线性筛代码:

for(int i = 2 ; i <= N ; i ++) {
    if(!bk[i]) Prime[++ tot] = i;
    for(int j = 1 ; j <= tot && Prime[j] * i <= N; j ++) {
        bk[Prime[j] * i] = 1;
        if(i % Prime[j] == 0) break;
    }
}
  • 讨论 (mu(x)) :

    (x) (in P) ,那么 (mu(x) = -1)

    筛质数时当 (P_j perp i) ,直接得到 (mu(P_j imes i) = -mu(i))

    筛质数时当 (P_j)(i) 不互质,那么 (P_j)(i) 有公共质因子,它们的公共质因子乘起来就会使得平方因子,那么 (mu(P_j imes i) = 0)

  • 讨论 (varphi(x):)

    倘若 (x in P) ,那么可以得到 (varphi(x) = x - 1)

    筛质数时当 (P_j perp i) ,直接得到 (varphi(P_j imes i) = varphi(P_j) imes varphi(i))

    筛质数时当 (P_j)(i) 不互质,那么 (P_j)(i) 有公共质因子 (P_j),那么 (varphi(P_j imes i) = P_j imes varphi(i))

  • 关于 (d(x):)

    倘若 (x in P),那么 (d(x) = 2)

    倘若筛质数的时候 (P_j perp i),那么 (d(P_j imes i) = d(P_j) imes d(i))

    倘若筛质数的时候 (P_j)(i) 不互质,设 (t) 是满足 (P_j^t | i) 的最大的 (t)(d(P_j imes i) = d(i) / (t + 1) imes(t + 2))

  • 关于 (sigma_1(x))

    (sigma_1(x) = ∏_{i = 1}^{i = k} (1 + p_i^1 +p_i^2 + ... + p_i^{a_i}))

    倘若 (x in P)(sigma_1(x) = x + 1)

    倘若 (i perp P_j),那么可以得到 (sigma_1(P_j imes i) = sigma_1(P_j) imes sigma(i))

    倘若 (i)(P_j) 不互质,那么根据上面的计算式,设 (t) 是满足 (P_j^t | i) 的最大的 (t), 可以得到 :

    (sigma_1(P_j imes i) = sigma_1(i) / sum(1 + P_j + P_j^2 +...+P_j^t) imes sum(1 + P_j + P_j^2 +...+P_j^t + P_j^{t + 1}))

关于筛 (d(x))(sigma_i(x)) 中如何处理那个 "(t)",就直接记录一个 (cnt) 数组表示每个数的最小值质因子在这个数分解质因数的时候指数是多少即可。具体写法就略过了。

对应模板:线性筛筛积性函数【模板】

题目选讲

Bzoj P4804 欧拉心算

(T) 次询问,每次询问:

(displaystyle sum_{i = 1}^{i = n} sum_{j = 1}^{j = n} varphi(gcd(i,j)))

(T leq 5 imes 10^3, n leq 10^7)

解法:

因为询问的组数到了 (5 imes 10^3) 组,所以考虑使用 (sqrt{n}) 能够出答案的方法。

预处理 (n leq 10^7) 的所有 (varphi(n)),同时预处理其前缀和,然后对于原题给出的式子进行化简:

(displaystyle sum_{i = 1}^{i = n} sum_{j = 1}^{j = n} varphi(gcd(i,j)) \ = displaystyle sum_{d = 1}^{d = n} varphi(d) sum_{i = 1}^{lfloor frac{n}{d} floor} sum_{j = 1}^{lfloor frac{n}{d} floor} [gcd(i,j) = 1] \ displaystyle = sum_{d = 1}^{n} varphi(d) (sum_{i = 1}^{lfloor frac{n}{d} floor} (varphi(i) * 2) - 1))

利用整除分块技巧即可 (O(sqrt{n})) 解决单组询问,非常 simple 的一道题。

(2) 亚线性算法筛积性函数

(2.1) 介绍:

主流算法有 (Min25) 筛,洲阁筛,杜教筛

好吧我不装了,我摊牌了,其实我只会杜教筛,于是我们来回忆一下杜教筛吧 (MuYC流下了菜逼的眼泪)

(2.2) 杜教筛

(2.3) 应用范围

筛某一个积性函数 (f(x)) 的前缀和。

对于 (f(x)) 的要求是,要求能够构造一个 (g(x)),使得 (g(x)) 以及 ((g * f)(x)) 的前缀和容易得到。

其中 (f*g) 表示的是 (f)(g)迪利克雷卷积((f*g)(n) = displaystyle sum_{d | n} f(d) * g(frac{n}{d}))

(2.4) 前置知识

下面先给出一些比较常见的数论函数:

  • (epsilon(x) = [x = 1])

  • (I(x) = 1)

  • (id(x) = x)

这里面比较特殊的只有 (epsilon(x)),它也被称作迪利克雷函数,同时它也是数论函数中的“单位元”,任意一个数论函数与之卷积都不变。

  • 几个比较基础的性质

    • (I * mu = epsilon) ,定义。

    • ((varphi * I)(n) = id(n)) ,其展开得到的式子是这样子的:((varphi * I)(n) = displaystyle sum_{d|n} varphi(d) * I(frac{n}{d}) = n)

    • ((mu * id)(n) = varphi(n))

      证明

      (varphi *I) = $id(n) ∴ $$(mu * id)(n) = (mu * I * varphi)(n)$

      (mu * I = epsilon)(∴(mu * id)(n) = (epsilon * varphi)(m))

      (epsilon) 为单位元函数,任意一个数论函数与之卷积都不变,所以可以得到结论:

      ((mu * id)(n) = varphi(n))

(2.5) 杜教筛使用方法

考虑有数论函数 (f,g),那么假设我们现在要求 (displaystyle sum_{i = 1}^{i = n} f(i)),设 (S(n) = displaystyle sum_{i = 1}^{i = n} f(i))

那么 (displaystyle sum_{i = 1}^{i = n} (f*g)(i) \ displaystyle = sum_{i = 1}^{i = n} sum_{d|i}g(d)*f(frac{i}{d}) \ = displaystyle sum_{d = 1}^{n}g(d) * (sum_{i = 1}^{lfloor frac{n}{d} floor} f(i)) \ = displaystyle sum_{d = 1}^{n}g(d) * S(lfloor frac{n}{d} floor))

我们就得到了: (displaystyle sum_{i = 1}^{i = n} (f*g)(i) = sum_{d = 1}^{n} g(d) * S(lfloor frac{n}{d} floor))

移项可得:(g(1) *S(n) = displaystyle sum_{i = 1}^{i = n} (f*g)(i) - sum_{d = 2}^{n} g(d) * S(lfloor frac{n}{d} floor))

整理得到:(S(n) = frac{displaystyle sum_{i = 1}^{i = n} (f*g)(i) - sum_{d = 2}^{n} g(d) * S(lfloor frac{n}{d} floor)}{g(1)})

至此,我们倘若可以很快的求出 (displaystyle sum_{i = 1}^{i = n} (f*g)(i)) 以及 (g) 函数的前缀和,我们可以利用整除分块技巧来完成优化。

  • (example_1) : 求 (displaystyle sum_{i = 1}^{i = n} varphi(i))

    不妨令函数 (g(x) = I(x))

    那么 ((varphi * g)(n) = n),设 (S(n) = displaystyle sum_{i = 1}^{i = n} varphi(i))

    那么 (displaystyle sum_{i = 1}^{i = n} (varphi * g)(i) = frac{(n + 1) * n}{2})

    利用上面的式子 (S(n) = frac{displaystyle sum_{i = 1}^{i = n} (f*g)(i) - sum_{d = 2}^{n} g(d) * S(lfloor frac{n}{d} floor)}{g(1)}) 就很容易得到得到答案。

  • (example_2) : 求 (displaystyle sum_{i = 1}^{i = n} mu)

    (g(x) = epsilon) 即可。

模板:Luogu P4213 【模板】杜教筛(Sum)

  • (example_3) : YZOJ 50045 八爷算数

    古有九章算术,今有八爷算数。
    

    ⑧ 是一个算数奇才,他有一天看到了一个这样的题目:

    给定一个 (n),现在你需要求出:

    (displaystyle sum_{i = 1}^{n} sum_{j = 1}^{n} sigma_1(gcd(i,j)))

    ⑧ 现在忙着 (AK) (IOI),不屑于算这个简单的东西,于是他就委托你来帮他解决问题了,聪明的你一定能够解答出这个问题。

    (n leq 10 ^ {10})

    解答:

    考虑对于式子进行化简,

    (displaystyle sum_{i = 1}^{n} sum_{j = 1}^{n} sigma_1(gcd(i,j)))

    (=) (displaystyle sum_{d = 1}^{n}sum_{i = 1}^{lfloor frac{n}{d} floor} sum_{j = 1}^{lfloor frac{n}{d} floor} sigma_1(d) imes [gcd(i,j) = 1])

    (= displaystyle sum_{d = 1}^{n}sigma_1(d) imes (sum_{i = 1}^{lfloor frac{n}{d} floor} varphi(i) * 2 - 1))

    考虑朴素计算 (displaystyle sum_{i = 1}^{n} sigma_1(i) = displaystyle sum_{i = 1}^{i = n} i imes lfloor frac{n}{i} floor)

    预处理前 (10^7)(sigma_1) 以及 (varphi) 然后就可以做到使用杜教筛筛 (varphi) ,前半部分直接暴力数论分块处理。

    复杂度 (O(n^{frac{3}{4}})) ?其实我也不太会算,但是其在处理 (10^{10}) 的情况下,在本菜鸡的辣鸡机子上是可以 2.5s 跑过的。

  • (example_4) : 求 (displaystyle sum_{i = 1}^{n} mu^2)

考虑设置函数 (g(n) = [n = k^2,k in N^{+}])

(f(n) = mu^2(n)), 设(displaystyle S(n) = sum_{i = 1}^{n} f(i))

(displaystyle sum_{i = 1}^{n} (f*g)(i))

(= displaystyle sum_{i = 1}^{n} sum_{d|i}f(d)*g(frac{n}{d}))

对于 (displaystyle sum_{d|i}f(d) * g(frac{n}{d})) 这个函数当且仅当 (d)(i) 的最大质因子的时候取到 (1)

那么可以得到 (displaystyle sum_{i = 1}^{n} (f*g)(i) = n)

那么根据杜教筛的套路来做:

(displaystyle S(n) = n - sum_{d = 2}^{n}g(d) * S(lfloor frac{n}{d} floor))

(= displaystyle n - sum_{d = 2}^{lfloor sqrt{n} floor} S(lfloor frac{n}{d^2} floor))

然后就可以做了,这个主要是要想到构造 (g)

数论好题

Luogu P5881 实验

给定 (n) 个二元组 ((a_i,b_i)),定义一个二元组的价值为:$c_i = $ (b_i) 分解质因数之后最大的指数

你现在可以把 (n) 个二元组任意组合形成若干组,每一组的组内 (c_i) 的最大值即为这个组的价值。

现在有 (m) 个询问,每次给定 (x_i),规定你第 (i) 次的分组中,不同组间的 (a_i,a_j) 的最大平方公因数不能大于 (x^2),现在要求你在满足限制的条件下分出最多的组数,你能得到的最大价值是多少。

因为我们只关心指数,所以说大于 (b^{frac{1}{3}}) 的质因子最多指数是 (2),我们只需要把 (b_i) 对于小于等于其 (frac{1}{3}) 次方的质因数分解即可得到 (c_i)

当然了,其实 (c_i) 也可以通过线性筛得到,但是貌似空间会炸裂。

考虑把 (a_i) 除掉其分解质因数后为指数奇数的质因数(只是除以一次),这样子就转化为了求任意两组之间的 (a_i,a_j),满足 (gcd(a_i,a_j) leq x^2)

例如如果原来的 (a_i = 72 = 2^3 imes 3^2),那么我们把它变为:(a_i = 36 = 2 ^2 imes 3^2)

然后建图,设立 (max(a_i)) 个点,将 (a_i) 的所有约数与 (i) 连边,然后边权设为这个约数的值,容易得到边的条数的量级是 (O(n ln max(a_i)))

不妨把给出的 (m) 个限制按照从大到小排序,一开始我们设这个 (x) 是无限大的,那么所有点都会单独分成一组。

我们每次把权值大于 (x^2) 的边加入这个图,然后将这些边连接的并查集合并,动态计算答案即可。

复杂度为 (O(n imes ln(MAX(a_i)) + m + n))

By MYCui
原文地址:https://www.cnblogs.com/MYCui/p/14983098.html