1900D - Small GCD

给定序列 \(A\),定义 \(f(a, b, c)\) 为 \(a, b, c\) 中最小的次小的数的 \(\gcd\),求:

\[\sum_{i = 1}^n \sum_{j = i + 1}^n \sum_{k = j + 1}^n f(a_i, a_j, a_k)
\]

题解

目前来说有两种方法,都十分有启发意义,但是有共同的开头。

考虑到 \(A\) 的顺序实际上没有什么关系,那么可以先对 \(A\) 排序,使得 \(i < j < k \iff a_i \le a_j \le a_k\),那么此时 \(f(a_i, a_j, a_k) = \gcd(a_i, a_j)\),从而答案的式子转化为:

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

接下来衍生出了两种做法。

莫比乌斯反演

准确来说应该是欧拉反演?

注意到:

\[\sum_{d | x} \varphi(d) = x
\]

那么我们可以将目标表达式写为:

\[\sum_{i = 1}^n \sum_{j = i + 1}^n \sum_{d | a_i, a_j} \varphi(d) \times (n - j)
\]

交换求和顺序,可以得到:

\[\begin{aligned}
& \sum_{d = 1}^V \varphi(d) \sum_{i = 1}^n \sum_{j = i + 1}^n [d | a_i] [d | a_j] (n - j) \\
= & \sum_{d = 1}^V \varphi(d) \sum_{j = 1}^n (n - j) [d | a_j] \sum_{i = 1}^{j - 1} [d | a_i]
\end{aligned}
\]

考虑对于每一个 \(d\),我们将满足 \(d | a_i\) 的数提出来作为集合 \(S\),那么这是容易 \(O(|S|)\) 求解的。

接下来我们只需要考虑其复杂度了。

注意到可以认为 \(\tau(n) = O(\sqrt n)\)(在本题值域限制中 \(\tau(n) \le 128\))也就是说每一个数至多在 \(128\) 个 \(S\) 中出现,那么我们可以知道 \(\sum |S| = O(128n)\),于是复杂度是合理的。

\(\tau(n)\) 表示 \(n\) 的因数个数。

提前预处理一下因数的分解,这是 \(O(V \log V)\) 的(由于值域很小,可以直接保存),以及 \(\varphi\) 即可。

总复杂度是 \(O(V \log V + 128n + n \log n)\)。

另类的枚举

回到基础的式子:

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

如果我们固定 \(j\),发现 \(\gcd(a_i, a_j)\) 一定是 \(a_j\) 的因数,并且 \(a_j\) 的因数至多有 \(128\) 个,这启发我们可以直接枚举 \(d = \gcd(a_i, a_j)\) 来算 \(d \times cnt_j \times (n - j)\)。

考虑 \(cnt_j\) 该如何计算,可以开一个桶 \(but_x\) 记录有多少个满足 \(x | a_i\) 的数。

发现并不能简单的 \(cnt_j = but_d\),因为这样会算重,考虑将会算重的部分给去掉。

具体来说,发现如果满足 \(d | \gcd(a_i, a_j)\),那么 \(x | d \to x | \gcd(a_i, a_j)\),也就是说 \(d\) 会在其所有因数再算一次。直接容斥有点麻烦,所以考虑直接在 \(but\) 上进行修改,也就是说进行 \(z | d, but_z \leftarrow but_z - but_d\) 的操作。

注意需要还原 \(but\)

于是就不需要容斥了……接着分析复杂度。

枚举因数同上,是 \(O(128n)\) 的,然而我们多了一个修改桶的操作,发现与枚举所有数的因数的复杂度是类同的,所以是 \(O(m \log m)\) 的。

怎么感觉复杂度假了?

总复杂度就是 \(O(128n + m \log m + n \log n)\),差不多。

总结

我首先想到的就是第一种做法……QwQ,数学学多了,但是仍然想了比较长的时间,基础还是不太牢。

第二种做法相对来说要亲民一些,但是比较难拓展到其他题上,也没法析出新的模型(因为完全可以被第一种方法取代),所以说第二种方法惜败。

最后再回顾一下莫反的 \(5\) 个经典套路:

  • \([x = 1] = \sum_{d | x} \mu(d)\)
  • \(x = \sum_{d | x} \varphi(d)\)
  • 整除分块
  • 枚举 \(\gcd\)
  • 枚举 \(T = kd\)

CF1900D - Small GCD 题解的更多相关文章

  1. HDU5726:GCD——题解

    题目:hdu的5726 (我原博客的东西,正好整理过来,属于st表裸题) (可以看出我当时有多么的菜--) 这道题写了一遍,然而蒟蒻的我的时间爆炸了-- 于是看了一下学长的代码(顺便在此处%一下学长) ...

  2. 洛谷 P2568 GCD 题解

    原题链接 庆祝一下:数论紫题达成成就! 第一道数论紫题.写个题解庆祝一下吧. 简要题意:求 \[\sum_{i=1}^n \sum_{j=1}^n [gcd(i,j)==p] \] 其中 \(p\) ...

  3. BZOJ2820:YY的GCD——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=2820 Description 神犇YY虐完数论后给傻×kAc出了一题给定N, M,求1<=x& ...

  4. CC DGCD:Dynamic GCD——题解

    https://vjudge.net/problem/CodeChef-DGCD https://www.codechef.com/problems/DGCD 题目大意: 给一颗带点权的树,两个操作: ...

  5. CH 4302 Interval GCD 题解

    题意 给定一个长度为N的数列A,以及M条指令 (N≤5* 10^5, M<=10^5),每条指令可能是以下两种之一: "C l r d",表示把 A[l],A[l+1],-, ...

  6. gcd 题解

    gcd Little White learned the greatest common divisor, so she plan to solve a problem: given \(x, n,\ ...

  7. [洛谷2257]YY的GCD 题解

    整理题目转化为数学语言 题目要我们求: \[\sum_{i=1}^n\sum_{i=1}^m[gcd(i,j)=p]\] 其中 \[p\in\text{质数集合}\] 这样表示显然不是很好,所以我们需 ...

  8. 洛谷 P2257 YY的GCD 题解

    原题链接 庆祝: 数论紫题 \(T4\) 达成! 莫比乌斯 \(T1\) 达成! yy 真是个 神犇 前记 之前我觉得: 推式子,直接欧拉筛,筛出个 \(\phi\),然后乱推 \(\gcd\) 就行 ...

  9. ABC136 E - Max GCD 题解

    题面 给定一个长度为 $N$ 的整数序列:$A_1, A_2, \ldots, A_n$. 您可以执行以下操作 $0 \sim K$ 次: 选择两个整数 $i$ 和 $j$,满足 $i \ne j$ ...

  10. Codeforces Round #271 (Div. 2)题解【ABCDEF】

    Codeforces Round #271 (Div. 2) A - Keyboard 题意 给你一个字符串,问你这个字符串在键盘的位置往左边挪一位,或者往右边挪一位字符,这个字符串是什么样子 题解 ...

随机推荐

  1. 使用Quorum Journal Manager(QJM)的HDFS NameNode高可用配置

    前面的一篇文章写到了hadoop hdfs 3.2集群的部署,其中是部署的单个namenode的hdfs集群,一旦其中namenode出现故障会导致整个hdfs存储不可用,如果是要求比较高的集群,有必 ...

  2. 力扣534(MySQL)-游戏玩法分析Ⅲ(中等)

    题目: 需求:请编写一个 SQL 查询,同时报告每组玩家和日期,以及玩家到目前为止玩了多少游戏.也就是说,在此日期之前玩家所玩的游戏总数.详细情况请查看示例. 查询结果格式在以下示例中: 对于 ID ...

  3. 力扣560(java&python)-和为k的子数组(中等)

    题目: 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的连续子数组的个数 . 示例 1: 输入:nums = [1,1,1], k = 2输出:2示例 2: 输入:n ...

  4. 力扣217(java&python)-存在重复元素(简单)

    题目: 给你一个整数数组 nums .如果任一值在数组中出现 至少两次 ,返回 true :如果数组中每个元素互不相同,返回 false . 示例 1: 输入:nums = [1,2,3,1]输出:t ...

  5. Flink 1.13,面向流批一体的运行时与 DataStream API 优化

    简介: 在 1.13 中,针对流批一体的目标,Flink 优化了大规模作业调度以及批执行模式下网络 Shuffle 的性能,以及在 DataStream API 方面完善有限流作业的退出语义. 本文由 ...

  6. 【ESSD技术解读-01】 云原生时代,阿里云块存储 ESSD 快照服务如何被企业级数据保护所集成?

    ​简介: 本文描述了阿里云块存储快照服务基于高性能 ESSD 云盘提升快照服务性能,提供轻量.实时的用户体验及揭秘背后的技术原理.依据行业发展及云上数据保护场景,为企业用户及备份厂商提供基于快照高级特 ...

  7. WPF 多线程下跨线程处理 ObservableCollection 数据

    本文告诉大家几个不同的方法在 WPF 里,使用多线程修改或创建 ObservableCollection 列表的数据 需要明确的是 WPF 框架下,非 UI 线程直接或间接访问 UI 是不合法的,设计 ...

  8. js原型,原型链(不断补充中)

    1.如何使用构造器? function Person(name, age) { this.name = name; this.age = age; } var man = new Person(&qu ...

  9. SpringBoot实现WebSocket发送接收消息 + Vue实现SocketJs接收发送消息

    SpringBoot实现WebSocket发送接收消息 + Vue实现SocketJs接收发送消息 参考: 1.https://www.mchweb.net/index.php/dev/887.htm ...

  10. Mybatis学习五($和#区别以及其他tips)

    1.$和#区别 1 #是将传入的值当做字符串的形式,eg:select id,name,age from student where id =#{id},当前端把id值1,传入到后台的时候,就相当于 ...