Counting Rhyme
题目信息
题目链接
Luogu CF1884D、Codeforces 1884D
题面翻译
给定长度为 \(n\) 的序列 \(a\)。对于 \(1\leq i<j\leq n\),若不存在 \(k\in[1,n]\) 使得 \(a_k\mid a_i\) 且 \(a_k\mid a_j\) 那么 \((i,j)\) 是好的。
求出好的数对数量。\(1\le a_i\le n\leq 10^6\)。
题目描述
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.
输入格式
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 $ .
输出格式
For each test case, output the number of good pairs.
样例 #1
样例输入 #1
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
样例输出 #1
0
3
26
26
124
82
提示
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_k\mid a_i\) 且 \(a_k\mid a_j\),所以 \(a_k\mid \gcd(a_i,a_j)\)。
假设 \(f(x)\) 表示 \(\gcd(a_i,a_j)=x\) 的对数。
我们发现这个很难求,于是我们在定义一个状态:
设 \(g(x)\) 表示 \(\gcd(a_i,a_j)\mid y\) 的个数,这个可以直接暴力 \(O(n\ln n)\) 求。
于是 \(f(x)=\displaystyle \sum_{i}\mu(i)g_{ix}\) 就行。
只需要再看 \(x\) 是否合法。同样可以把不合法的筛掉,即 \(gcd(a_i,a_j)\) 不能是 \(a_k\) 的倍数。\(O(n\ln n)\)。
结束。
代码
#include<bits/stdc++.h>
#pragma G++ optimize(2)
#define int long long
using namespace std;
const int MAXN = 1e6+10;
int mu[MAXN+10],prime[MAXN+10];
bitset<MAXN+10> is_prime;
void Euler_sieve(){
mu[1] = 1;
for(int i = 2;i<MAXN;i++){
if(!is_prime[i]){
prime[++prime[0]] = i;
mu[i] = -1;
}
for(int j = 1;j<=prime[0]&&i*prime[j]<MAXN;j++){
is_prime[i*prime[j]] = 1;
if(i%prime[j]==0){
mu[i*prime[j]] = 0;
break;
}else{
mu[i*prime[j]] = -mu[i];
}
}
}
}
int T,n,a[MAXN+10],g[MAXN+10];
int sum[MAXN+10] = {0};bitset<MAXN+10> vis,be;
signed main(){
Euler_sieve();
scanf("%lld",&T);
while(T--){
scanf("%lld",&n);
vis.reset();be.set();
for(int i = 1;i<=n;i++) sum[i] = 0;
for(int i = 1;i<=n;i++){
scanf("%lld",&a[i]);
vis[a[i]] = 1;
sum[a[i]]++;
}
int _ = vis._Find_first();
while(_<=n){
for(int i = _;i<=n;i+=_){
be[i] = 0;
}
_ = vis._Find_next(_);
}
for(int i = 1;i<=n;i++){
g[i] = 0;
for(int j = i;j<=n;j+=i){
g[i] += sum[j];
}
g[i] = g[i]*(g[i]-1)/2;
}
int ans = 0;
for(int i = 1;i<=n;i++){
for(int j = 1;j*i<=n;j++){
ans += g[i*j]*mu[j]*be[i];
}
}
printf("%lld\n",ans);
}
return 0;
}
tag
Codeforces
数学、容斥原理

浙公网安备 33010602011771号