HDU 5072 容斥原理

#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 一模一样了。

你可能感兴趣的:(HDU 5072 容斥原理)