首页 > 代码库 > [HDU 5072] Coprime 莫比乌斯反演
[HDU 5072] Coprime 莫比乌斯反演
题意
? 给定一个长度为 $n$ 的序列 $A = \left\{ a_1, a_2, ..., a_n \right\}$ .
? 问有多少个三元组 $(i, j, k)(i \ne j, i \ne k, j \ne k)$ , 满足 $\left\{ \begin{aligned} & a_i \perp a_j \\ & a_i \perp a_k \\ & a_j \perp a_k \end{aligned} \right.$ 或 $\left\{ \begin{aligned} & a_i \not \perp a_j \\ & a_i \not \perp a_k \\ & a_j \not \perp a_k \end{aligned} \right.$ .
? $1 \le n, a_i \le {10}^5$ .
预备知识
? $k | (x, y) \Leftrightarrow \left\{ \begin{aligned} & k | x \\ & k | y \end{aligned} \right.$
? 证明 (1) 必要性.
? $k | (x, y) , (x, y) | x, (x, y) | y \Rightarrow k | x, k | y$ .
? (2) 充分性.
? $\exists p, q \in \mathbb{Z}, ~s.t.~ px + qy = (x, y)$ .
? $k | x, k | y \Rightarrow k | px + qy \Rightarrow k | (x, y)?$ .
? $g_n = \sum_{d | n} f_n \Leftrightarrow f_n = \sum_{d | n} \mu(d) g(\frac{n}{d})$ .
? 由 $f_1, f_2, ..., f_n$ 求 $g_1, g_2, ..., g_n$ : 从小到大枚举 $d$ , 将 $f_d$ 加到 $g_d, g_{2d}, g_{3d}, ...$ .
? 由 $g_1, g_2, ..., g_n$ 求 $f_1, f_2, ..., f_n$ :
? 方法一 从小到大枚举 $d$ , 此时我们已经算出 $f_1, f_2, ..., f_d$ , 将 $g_{2d}, g_{3d}, ..., g_{kd}$ 减去 $f_d$ .
? 方法二 反演公式.
?
? $g_n = \sum_{n | d} f_d \Leftrightarrow f_n = \sum_{n | d} \mu(\frac{d}{n}) g(d)$
? 由 $f_1, f_2, ..., f_n$ 求 $g_1, g_2, ..., g_n$ : 枚举 $d$, 将 $f_d, f_{2d}, ...$ 加到 $g_d$ .
? 由 $g_1, g_2, ..., g_n$ 求 $f_1, f_2, ..., f_n$ :
? 方法一 从大到小枚举 $d$ , 将 $g_d$ 减去 $f_{2d}, f_{3d}, ...$ 得到 $f_d$ .
? 方法二 反演公式.
分析
? $n$ 个点的完全图, 边有两种颜色, 求同色三角形个数.
? 减法原理, $\binom{n}{3} - 不同色三角形个数$ .
? 枚举每个点, 算出该点除外的互质个数 $a$ , 该点除外的不互质个数 $b$ , 那么贡献 $a \times b$ .
? 发现每个不同色三角形, 我们恰好算了两次, 所以 $\frac{1}{2} (\sum a\times b)$ 即可.
? 当 $a_i = 1$ 时, 不产生贡献.
? 当 $a_i \ne 1$ 时, $该点除外的互质个数 = 互质个数 = a$ , $该点除外的不互质个数 = 不互质个数 - 1 = n - 1 - a$ .
? 给定 $a_1, a_2, ..., a_n$ , 求与 $x$ 互质的数的个数.
? 设 $c_d = \sum_{i} [a_i = d]$ , $f_x$ 为与 $x$ 互质的数的个数.
$$\begin{aligned} f_x & = \sum{d} [d \perp x] c_d \\ & = \sum_{k | d, d | x}\mu(k)c_d \\ & = \sum_{k | x} \mu(k) \sum_{k | d} c_d \end{aligned}$$
? 枚举 $k$ , $O(\frac{n}{k})$ 求 $\sum_{k | d}c_d$ , 再 $O(\frac{n}{k})$ 对 $f_k, f_{2k}, ..., f_{pk}, ...$ 进行贡献.
? 总时间复杂度 $O(n \log n)$ .
?
实现
#include <cstdio> #include <cstring> #include <cstdlib> #include <cctype> #define F(i, a, b) for (register int i = (a); i <= (b); i++) #define LL long long const int N = 100005; const int A = 100000; bool v[N]; int p[N], tot, mu[N]; int n, a[N]; LL c[N], f[N]; LL res; inline int rd(void) { int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1; int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f; } int main(void) { #ifndef ONLINE_JUDGE freopen("hdu5072.in", "r", stdin); freopen("hdu5072.out", "w", stdout); #endif v[1] = true, mu[1] = 1; F(i, 2, A) { if (!v[i]) p[++tot] = i, mu[i] = -1; for (int j = 1; i * p[j] <= A && j <= tot; j++) { v[i * p[j]] = true; if (i % p[j] != 0) mu[i * p[j]] = -mu[i]; else break; } } for (int nT = rd(), t = 1; t <= nT; t++) { memset(a, 0, sizeof a); n = rd(); F(i, 1, n) a[i] = rd(); memset(c, 0, sizeof c), memset(f, 0, sizeof f); F(i, 1, n) c[a[i]]++; F(k, 1, A) if (mu[k] != 0) { LL t = 0; for (int d = k; d <= A; d += k) t += c[d]; t *= mu[k]; for (int x = k; x <= A; x += k) f[x] += t; } res = 0; F(i, 1, n) if (a[i] != 1) res += f[a[i]] * (n - 1 - f[a[i]]); printf("%I64d\n", 1LL * n * (n-1) * (n-2) / 6 - res / 2); } return 0; }
[HDU 5072] Coprime 莫比乌斯反演