题解:CF1884D Counting Rhyme
题意
给定长度为
我们称一对下标
思路
易知,若
不妨设
那么题目所求就可以转化为
考虑枚举最大公因数:
把
易发现答案可以在调和级数
::::success[Code]
#include <bits/stdc++.h>
#define inl inline
#define ls (p << 1)
#define rs (p << 1 | 1)
#define Cst constexpr
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define pb(x) push_back(x)
#define ppc(x) __builtin_popcount(x)
#define mems(x, v) memset((x), (v), sizeof(x))
#define memc(x, y) memcpy((x), (y), sizeof(x))
#define All(x) (x).begin(), (x).end()
using LL = long long;
using ULL = unsigned long long;
using namespace std;
Cst int N = 1e6 + 5;
auto FIO = []() {
return cin.tie(0)->sync_with_stdio(0), 0;
}();
int n, a[N], cnt[N], tot[N]; LL f[N];
bitset<N> g;
void Solve() {
cin >> n;
for (int i = 1; i <= n; ++i) cnt[i] = f[i] = tot[i] = 0, g[i] = 1;
for (int i = 1; i <= n; ++i)
cin >> a[i], ++cnt[a[i]];
for (int i = 1; i <= n; ++i) {
for (int j = i; j <= n; j += i) {
tot[i] += cnt[j];
if (cnt[i]) g[j] = 0;
}
}
LL res = 0;
for (int i = n; i >= 1; --i) {
f[i] = (LL)tot[i] * (tot[i] - 1) / 2;
for (int j = i << 1; j <= n; j += i) f[i] -= f[j];
res += f[i] * g[i];
}
cout << res << '\n';
}
int main() {
int T; cin >> T;
while (T--) Solve();
}
::::