#include <cstring>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 1E5 + 10;
int T, N, X, inp[maxn], tol[maxn];
std::vector<long long> v;
vector<long long>& GetPrimefun(long long n)
{
v.clear();
for (long long i = 2; i * i <= n; i++)
if (n % i == 0)
{
v.push_back(i);
while (n % i == 0) n /= i;
}
if (n > 1) v.push_back(n);
return v;
}
long long solve(long long x, long long n)
{
std::vector<long long>& v = GetPrimefun(n);
long long sum = 0, tmp, cnt;
for (long long i = 1; i < (1 << v.size()); i++)
{
tmp = 1, cnt = 0;
for (long long j = 0; j < v.size(); j++)
if (i & (1LL << j)) tmp *= v[j], cnt++;
sum += (cnt & 1 ? 1 : -1) * tol[tmp];
}
return max(0LL, (sum - 1) * (x - sum));
}
int main(int argc, char const *argv[])
{
scanf("%d", &T);
while (T--)
{
long long ans = 0;
scanf("%d", &N);
memset(inp, 0, sizeof(inp));
memset(tol, 0, sizeof(tol));
for (int i = 0; i < N; i++)
scanf("%d", &X), inp[X]++;
for (int i = 1; i < maxn; i++)
for (int j = i; j < maxn; j += i)
tol[i] += inp[j];
for (int i = 1; i < maxn; i++)
if (inp[i])
ans += solve(N, i);
printf("%lld\n", (long long)N * (N - 1) * (N - 2) / 6 - ans / 2);
}
return 0;
}
和HDU 4135 原理一样,然而TLE,算法O(n^1.5) 题解为O(Nlogn);
把vector由每次创建新的改为每次清空,972ms惊险过题。
如果三个数a, b, c不符合条件,那么一定有一对是互质的,有一对是不互质的。不妨令a, b互质,b, c不互质。于是我们可以枚举b来统计答案。在除了b自己的所有数中,要么与b互质,要么与b不互质。假设n个数中有x个与b不互质的数,那么b对答案的贡献就是(x - 1) * (n - x)。
然后就和HDU 4135 一模一样了。