D. Counting Rhyme

D. Counting Rhyme

You are given an array of integers $a_1, a_2, \ldots, a_n$.

A pair of integers $(i, j)$, such that $1 \le i < j \le n$, is called good, if there does not exist an integer $k$ ($1 \le k \le n$) such that $a_i$ is divisible by $a_k$ and $a_j$ is divisible by $a_k$ at the same time.

Please, find the number of good pairs.

Input

Each test contains multiple test cases. The first line contains the number of test cases $t$ ($1 \le t \le 2 \cdot 10^4$). The description of the test cases follows.

The first line of each test case contains a single integer $n$ ($1 \le n \le 10^6$).

The second line of each test case contains $n$ integers $a_1, a_2, \ldots, a_n$ ($1 \le a_i \le n$).

It is guaranteed that the sum of $n$ over all test cases does not exceed $10^6$.

Output

For each test case, output the number of good pairs.

Example

input

6
4
2 4 4 4
4
2 3 4 4
9
6 8 9 4 6 8 9 4 9
9
7 7 4 4 9 9 6 2 9
18
10 18 18 15 14 4 5 6 8 9 10 12 15 16 18 17 13 11
21
12 19 19 18 18 12 2 18 19 12 12 3 12 12 12 18 19 16 18 19 12

output

0
3
26
26
124
82

Note

In the first test case, there are no good pairs.

In the second test case, here are all the good pairs: $(1, 2)$, $(2, 3)$, and $(2, 4)$.

 

解题思路

  对于数对 $(a_i, a_j)$,如果存在某个 $a_k$ 使得 $a_k \mid a_i$ 且 $a_k \mid a_j$,意味着 $a_k$ 是 $a_i$ 和 $a_j$ 的公倍数,并且 $a_k \mid \operatorname{gcd}(a_i, a_j)$。为此我们可以根据数对的 $\operatorname{gcd}$ 来进行分类,那么对于所有 $\operatorname{gcd}$ 是 $d$ 的数对,如果数组中存在某个 $a_k \mid d$,那么这些数对都不能被作为答案统计。

  现在来求最大公约数为 $d$ 的数对的数量。很明显要组成数对的元素必然是 $d$ 的倍数,那么这些元素的数量就等于 $s = c_{d} + c_{2d} + c_{kd}$,其中 $c_{x}$ 表示数组 $a$ 中元素 $x$ 的个数,$k = \left\lfloor \frac{n}{d} \right\rfloor$。那么从这些元素中任意选择两个组合,就会有 $C_{s}^{2}$ 个数对,但事实上这些数对的最大公约数不一定是 $d$,比如 $(4d, 6d)$,其最大公约数应该为 $2d$。

  因此 $C_{s}^{2}$ 本质上是所有最大公约数是 $d$ 的倍数的数对的数量。对此我们再定义 $f_{d}$ 表示最大公约数确切为 $d$ 的数对的数量,所以就有 $C_{s}^{2} = \sum\limits_{i=1}^{k}{f_{i \cdot d}}$,推出 $f_{d} = C_{s}^{2} - f_{2d} - \cdots - f_{kd}$。所以我们可以从大到小倒着枚举 $d$ 来求 $f_{d}$,此时 $f_{2d}, \ldots, f_{kd}$ 都已经算出来了,这一步的时间复杂度为 $O\left(\sum\limits_{i=1}^{n}{\frac{n}{i}}\right) \approx O(n \log{n})$。

  最后再枚举 $a$ 中出现过的元素 $a_i$,以及 $a_i$ 的倍数,那么最大公约数是 $a_i$ 的倍数的数对都被筛掉,这一步的时间复杂度也是 $O\left(\sum\limits_{i=1}^{n}{\frac{n}{i}}\right) \approx O(n \log{n})$。

  AC 代码如下,时间复杂度为 $O(n \log{n})$:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 1e6 + 10;

int cnt[N];
LL f[N];
bool vis[N];

void solve() {
    int n;
    scanf("%d", &n);
    memset(cnt, 0, n + 10 <<2);
    for (int i = 0; i < n; i++) {
        int x;
        scanf("%d", &x);
        cnt[x]++;
    }
    for (int i = n; i; i--) {
        int t = 0;
        for (int j = i; j <= n; j += i) {
            t += cnt[j];
        }
        f[i] = t * (t - 1ll) >> 1;
        for (int j = i + i; j <= n; j += i) {
            f[i] -= f[j];
        }
    }
    memset(vis, 0, n + 10);
    for (int i = 1; i <= n; i++) {
        if (cnt[i]) {
            for (int j = i; j <= n; j += i) {
                vis[j] = true;
            }
        }
    }
    LL ret = 0;
    for (int i = 1; i <= n; i++) {
        if (!vis[i]) ret += f[i];
    }
    printf("%lld\n", ret);
}

int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        solve();
    }
    
    return 0;
}

 

参考资料

  Codeforces Round #904 (Div. 2) Editorial:https://codeforces.com/blog/entry/121618

posted @ 2023-10-29 20:23  onlyblues  阅读(95)  评论(1编辑  收藏  举报
Web Analytics