给定一个排列 $a_1 \sim a_n$,其中 $1 \le n \le 2 \times 10^5$,求:
$$
\sum_{i=1}^{n}\sum_{j=i}^{n}[i \perp j] [a_i \perp a_j]
$$
发现这个 $j$ 的枚举不是从 $1$ 开始的,有些不爽,不妨看看能换成啥:
$$
\begin{aligned}
&\sum_{i=1}^{n}\sum_{j=1}^{n}[i \perp j][a_i \perp a_j] \\
=&[a_1=1]+2\sum_{i=1}^{n}\sum_{j=i+1}^{n}[i \perp j][a_i \perp a_j] \\
=&[a_1=1]-2[a_1=1]+2\sum_{i=1}^{n}\sum_{j=i}^{n}[i \perp j][a_i \perp a_j] \\
\end{aligned}
$$
也就是说:
$$
\sum_{i=1}^{n}\sum_{j=i}^{n}[i \perp j] [a_i \perp a_j]=\frac{[a_1=1]+\sum_{i=1}^{n}\sum_{j=1}^{n}[i \perp j][a_i \perp a_j]}{2}
$$
于是只需要关心 $j$ 从 $1$ 开始的那个式子就行了,这样就很好做了
设:
$$
F(d)=\sum_{i=1}^{n}\sum_{j=1}^{n}[d \mid i][d \mid j] [a_i \perp a_j]
$$
那么有:
$$
f(d)=\sum_{i=1}^{n}\sum_{j=1}^{n}[\gcd(i,j)=d][a_i \perp a_j]=(F \times \mu)(d)
$$
答案就是 $f(1)$ 了
考虑如何计算 $F(d)$,一个比较显然的思路就是:
$$
\begin{aligned}
F(d)=&\sum_{i=1}^{n}\sum_{j=1}^{n}[d \mid i][d \mid j] [a_i \perp a_j] \\
=&\sum_{t=1}^{n}\mu(t) \left(\sum_{i=1}^{n} [d \mid i] [t \mid a_i] \right)^2
\end{aligned}
$$
在枚举 $d$ 的时候,可以顺便把 $d$ 的所有倍数位置的 $a_i$ 都搞出来,然后放到一个 $g$ 数组中,其中 $g_x=\sum_{i=1}^{n} [d \mid i][x \mid a_i]$,这个可以直接枚举 $a_i$ 的约数后更新
这样一来计算 $F(d)$ 的时候只需要枚举所有 $d$ 的倍数的约数的并集就行了
不妨分析一下这种暴力的时间复杂度:
首先每一个 $a_i$ 会在 $i$ 的某个约数的时候被枚举到,之后还会枚举 $a_i$ 的约数,因此这部分的时间复杂度是 $O(\sum_{i=1}^{n}\sigma_0^2(i))$,经打表计算,在 $n =2 \times 10^5$ 的时候大概是 $10^7$ 左右的级别
至于其它地方的时间复杂度,都小于这个时间复杂度,因此总的时间复杂度就是 $O(\sum_{i=1}^{n}\sigma_0^2(i))$ 左右了


1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N = 2e5 + 10; 5 vector<int> g[N]; 6 ll ans, f[N], F[N], cnt[N]; 7 int n, mu[N], pri[N], tot, vis[N], a[N], fafa[N]; 8 9 int main() { 10 scanf("%d", &n); 11 for(int i = 1 ; i <= n ; ++ i) scanf("%d", &a[i]); 12 13 mu[1] = 1; 14 for(int i = 2 ; i <= n ; ++ i) { 15 if(!vis[i]) { 16 mu[i] = -1; 17 pri[++ tot] = i; 18 } 19 for(int j = 1 ; j <= tot && i * pri[j] <= n ; ++ j) { 20 vis[i * pri[j]] = 1; 21 if(i % pri[j] == 0) break; 22 mu[i * pri[j]] = -mu[i]; 23 } 24 } 25 26 for(int i = 1 ; i <= n ; ++ i) 27 for(int j = i ; j <= n ; j += i) 28 g[j].push_back(i); 29 30 for(int d = 1 ; d <= n ; ++ d) { 31 for(int i = d ; i <= n ; i += d) { 32 for(int j = 0 ; j < g[a[i]].size() ; ++ j) { 33 ++ cnt[g[a[i]][j]]; 34 } 35 } 36 37 int T = ++ fafa[0]; 38 for(int i = d ; i <= n ; i += d) { 39 for(int j = 0 ; j < g[a[i]].size() ; ++ j) { 40 int x = g[a[i]][j]; 41 if(fafa[x] == T) continue; 42 fafa[x] = T; 43 f[d] += mu[x] * cnt[x] * cnt[x]; 44 cnt[x] = 0; 45 } 46 } 47 } 48 49 // for(int i = 1 ; i <= n ; ++ i) 50 // for(int j = i ; j <= n ; j += i) 51 // F[i] += f[j] * mu[j / i]; 52 // ans = (F[1] + (a[1] == 1)) / 2; 53 54 for(int i = 1 ; i <= n ; ++ i) 55 ans += f[i] * mu[i]; 56 ans = (ans + (a[1] == 1)) / 2; 57 printf("%lld\n", ans); 58 }