题目大意
给定长度为 n ( 3 ≤ n ≤ 3 × 1 0 5 ) n(3\le n\le 3\times 10^5) n(3≤n≤3×105) 的数组 a ( 1 ≤ a i ≤ 3 × 1 0 5 ) a(1\le a_i\le 3\times 10^5) a(1≤ai≤3×105),其中的元素互不相同。问有多少三元组满足最大数与最小数互质。两个三元组不同当且仅当存在数 x x x 出现在三元组 A A A 中而不出现在三元组 B B B 中。
题解
容易发现数组 a a a 的顺序对答案没有影响。为了方便统计答案,我们人为地给它安排顺序,也就是对 a a a 数组排序。
显然,当确定了三元组中最大值和最小值后,中间值可以随意选,只需要满足它位于最大最小值之间。也就是说,当最大值为 a i a_i ai 而最小值为 a j a_j aj(显然 j < i j<i j<i)时,中间值有 i − j − 1 i-j-1 i−j−1 种取值。
易得
a n s = ∑ g c d ( a i , a j ) = 1 , j < i ( i − j − 1 ) ans=\sum\limits_{gcd(a_i,a_j)=1,j<i}(i-j-1) ans=gcd(ai,aj)=1,j<i∑(i−j−1)
对于每个 i i i 考虑其贡献,有
a n s = ∑ i = 1 n ∑ g c d ( a i , a j ) ( i − j − 1 ) = ∑ i = 1 n ∑ j = 1 i − 1 ( i − j − 1 ) [ g c d ( a i , a j ) = 1 ] ans=\sum\limits_{i=1}^{n}\sum\limits_{gcd(a_i,a_j)}(i - j - 1)\\ =\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{i-1}(i - j - 1)[gcd(a_i, a_j)=1] ans=i=1∑ngcd(ai,aj)∑(i−j−1)=i=1∑nj=1∑i−1(i−j−1)[gcd(ai,aj)=1]
以下是莫反技巧推导。
a n s = ∑ i = 1 n ∑ j = 1 i − 1 ( i − j − 1 ) [ g c d ( a i , a j ) = 1 ] = ∑ i = 1 n ∑ j = 1 i − 1 ( i − j − 1 ) ∑ k ∣ g c d ( a i , a j ) μ ( k ) ans=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{i-1}(i - j - 1)[gcd(a_i, a_j)=1]\\ =\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{i-1}(i - j - 1)\sum\limits_{k|gcd(a_i, a_j)}\mu(k) ans=i=1∑nj=1∑i−1(i−j−1)[gcd(ai,aj)=1]=i=1∑nj=1∑i−1(i−j−1)k∣gcd(ai,aj)∑μ(k)
考虑将 μ \mu μ 提到最前面,变换枚举对象,枚举 d = g c d ( a i , a j ) d=gcd(a_i,a_j) d=gcd(ai,aj)。
a n s = ∑ d = 1 a n μ ( d ) ∑ d ∣ a i ∑ d ∣ a j , j < i ( i − j − 1 ) ans=\sum\limits_{d=1}^{a_n}\mu(d)\sum\limits_{d|a_i}\sum\limits_{d|a_j,j<i}(i-j-1) ans=d=1∑anμ(d)d∣ai∑d∣aj,j<i∑(i−j−1)
考虑分离 i i i 和 j j j.
a n s = ∑ d = 1 a n μ ( d ) ∑ d ∣ a i ( ∑ d ∣ a j , j < i ( i − 1 ) − ∑ d ∣ a j , j < i j ) ans=\sum\limits_{d=1}^{a_n}\mu(d)\sum\limits_{d|a_i}\left(\sum\limits_{d|a_j,j<i}(i-1)-\sum\limits_{d|a_j,j<i}j\right) ans=d=1∑anμ(d)d∣ai∑ d∣aj,j<i∑(i−1)−d∣aj,j<i∑j
整理出容易解决的式子:
a n s = ∑ d = 1 a n μ ( d ) ∑ d ∣ a i ( ( i − 1 ) ∑ j = 1 i − 1 [ d ∣ a j ] − ∑ d ∣ a j , j < i j ) ans=\sum\limits_{d=1}^{a_n}\mu(d)\sum\limits_{d|a_i}\left((i-1)\sum\limits_{j=1}^{i-1}[d|a_j]-\sum\limits_{d|a_j,j<i}j\right) ans=d=1∑anμ(d)d∣ai∑ (i−1)j=1∑i−1[d∣aj]−d∣aj,j<i∑j
μ ( d ) \mu(d) μ(d) 可以欧拉筛线性预处理。
对于 d d d 和 a i a_i ai,可以直接枚举,时间复杂度为 O ( n + n 2 + n 3 + ⋯ + n n ) = O ( n × ( 1 + 1 2 + 1 3 + ⋯ + n n ) ) = O ( n ln n ) O(n+\dfrac n 2+\dfrac n 3+\cdots+\dfrac n n)=O(n\times (1+\dfrac 1 2+\dfrac 1 3+\cdots+\dfrac n n))=O(n\ln n) O(n+2n+3n+⋯+nn)=O(n×(1+21+31+⋯+nn))=O(nlnn).
关于 j j j 的项,可以在枚举 i i i 的过程中累加统计,因为 j j j 必定小于 i i i,也就是说之前其实已经遍历过 j j j 了。具体见代码。
总的时间复杂度是 O ( n ln n ) O(n\ln n) O(nlnn).
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 300005;
int n, a[N], mu[N], pri[N], cnt = 0, vis[N], b[N];
LL ans = 0;
void init() {
mu[1] = 1;
for (int i = 2; i < N; i++) {
if (!vis[i]) pri[++cnt] = i, mu[i] = -1;
for (int j = 1; j <= cnt && i * pri[j] < N; j++) {
vis[i * pri[j]] = 1;
if (i % pri[j] == 0) break;
mu[i * pri[j]] = -mu[i];
}
}
}
int main() {
init();//莫比乌斯函数线性筛
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; i++) b[a[i]] = i;//b[i]表示值为i的元素在数组中出现的位置
for (int d = 1; d <= a[n]; d++) {//枚举d
LL sum = 0, s1 = 0, s2 = 0;//sum统计后面的一大串式子,s1统计前i-1个数有多少出现在数组中且整除d,s2统计出现在数组中且整除d的元素的位置(下标)和
for (int i = d; i <= a[n]; i += d)//枚举值,值在数组中的位置是b[i]
if (b[i])//数组中有i这个数
sum += 1ll * (b[i] - 1) * s1 - s2, s1++, s2 += b[i];//维护
ans += sum * mu[d];
}
printf("%lld", ans);
return 0;
}