题意
luogu - P4619 [SDOI2018]旧试题
∑ i = 1 A ∑ j = 1 B ∑ k = 1 C σ 0 ( i j k ) \sum_{i=1}^A\sum_{j=1}^B\sum_{k=1}^C \sigma_0(ijk)
i = 1 ∑ A j = 1 ∑ B k = 1 ∑ C σ 0 ( i j k )
σ 0 ( x ) \sigma_0(x) σ 0 ( x ) 表 x x x 约数个数。
多测 T ≤ 10 T\le 10 T ≤ 1 0 ,1 ≤ ∑ max ( A , B , C ) ≤ 2 × 2 × 1 0 5 1\le \sum \max(A,B,C)\le 2\times 2\times 10^5 1 ≤ ∑ max ( A , B , C ) ≤ 2 × 2 × 1 0 5 。
题解
下文简记 gcd ( i , j ) = ( i , j ) \gcd(i,j)=(i,j) g cd( i , j ) = ( i , j ) ,lcm ( i , j ) = [ i , j ] \operatorname{lcm}(i,j)=[i,j] l c m ( i , j ) = [ i , j ]
显然有结论 ,就当作 σ 0 \sigma_0 σ 0 的性质吧。
σ 0 ( i j k ) = ∑ x ∣ i ∑ y ∣ j ∑ z ∣ k [ ( x , y ) = 1 ] [ ( x , y ) = 1 ] [ ( y , z ) = 1 ] \sigma_0(ijk)=\sum_{x|i}\sum_{y|j}\sum_{z|k} [(x,y)=1][(x,y)=1][(y,z)=1]
σ 0 ( i j k ) = x ∣ i ∑ y ∣ j ∑ z ∣ k ∑ [ ( x , y ) = 1 ] [ ( x , y ) = 1 ] [ ( y , z ) = 1 ]
代回原式,按照套路写成 ϵ \epsilon ϵ
∑ i = 1 A ∑ j = 1 B ∑ k = 1 C ∑ x ∣ i ∑ y ∣ j ∑ z ∣ k ϵ ( ( x , y ) ) ϵ ( ( x , y ) ) ϵ ( ( y , z ) ) \sum_{i=1}^A\sum_{j=1}^B\sum_{k=1}^C \sum_{x|i}\sum_{y|j}\sum_{z|k} \epsilon((x,y))\epsilon((x,y))\epsilon((y,z))
i = 1 ∑ A j = 1 ∑ B k = 1 ∑ C x ∣ i ∑ y ∣ j ∑ z ∣ k ∑ ϵ ( ( x , y ) ) ϵ ( ( x , y ) ) ϵ ( ( y , z ) )
反演,
∑ i = 1 A ∑ x ∣ i ∑ j = 1 B ∑ y ∣ j ∑ k = 1 C ∑ k ∣ z ∑ d 1 ∣ x , d 1 ∣ y μ ( d 2 ) ∑ d 2 ∣ x , d 2 ∣ z μ ( d 2 ) ∑ d 3 ∣ y , d 3 ∣ z μ ( d 3 ) \sum_{i=1}^A\sum_{x|i}\sum_{j=1}^B\sum_{y|j}\sum_{k=1}^C\sum_{k|z} \sum_{d_1|x,d_1|y} \mu(d_2)\sum_{d_2|x,d_2|z} \mu(d_2)\sum_{d_3|y,d_3|z} \mu(d_3)\\
i = 1 ∑ A x ∣ i ∑ j = 1 ∑ B y ∣ j ∑ k = 1 ∑ C k ∣ z ∑ d 1 ∣ x , d 1 ∣ y ∑ μ ( d 2 ) d 2 ∣ x , d 2 ∣ z ∑ μ ( d 2 ) d 3 ∣ y , d 3 ∣ z ∑ μ ( d 3 )
显然有 d 1 ∣ i , d 1 ∣ j , d 2 ∣ i , d 2 ∣ k , d 3 ∣ j , d 3 ∣ k d_1|i,d_1|j,d_2|i,d_2|k,d_3|j,d_3|k d 1 ∣ i , d 1 ∣ j , d 2 ∣ i , d 2 ∣ k , d 3 ∣ j , d 3 ∣ k ,即 [ d 1 , d 2 ] ∣ i , [ d 2 , d 3 ] ∣ j , [ d 1 , d 3 ] ∣ k [d_1,d_2]\mid i,\,[d_2,d_3]\mid j,\,[d_1,d_3]\mid k [ d 1 , d 2 ] ∣ i , [ d 2 , d 3 ] ∣ j , [ d 1 , d 3 ] ∣ k 。
交换求和顺序,i ′ , j ′ , k ′ i',j',k' i ′ , j ′ , k ′ 分别表示为 [ d 1 , d 2 ] , [ d 2 , d 3 ] , [ d 1 , d 3 ] [d_1,d_2],[d_2,d_3],[d_1,d_3] [ d 1 , d 2 ] , [ d 2 , d 3 ] , [ d 1 , d 3 ] 的几倍。
再考虑 ∑ x ∣ i \sum_{x\mid i} ∑ x ∣ i , 因为有 x ∣ i , d 1 ∣ x , d 2 ∣ x x\mid i,\,d_1\mid x,\,d_2\mid x x ∣ i , d 1 ∣ x , d 2 ∣ x ,所以 x x x 为 [ d 1 , d 2 ] [d_1,d_2] [ d 1 , d 2 ] 的倍数,且为 x x x 为 i i i 的因数,这样的 x x x 有 σ 0 ( i / [ d 1 , d 2 ] ) = σ 0 ( i ′ ) \sigma_0(i/[d_1,d_2])=\sigma_0(i') σ 0 ( i / [ d 1 , d 2 ] ) = σ 0 ( i ′ ) 个。y , z y,z y , z 同理。
∑ d 1 = 1 min ( A , B ) ∑ d 2 = 1 min ( A , C ) ∑ d 3 = 1 min ( B , C ) μ ( d 2 ) μ ( d 1 ) μ ( d 3 ) ∑ i ′ = 1 ⌊ A / [ d 1 , d 2 ] ⌋ σ 0 ( i ′ ) ∑ j ′ = 1 ⌊ B / [ d 1 , d 3 ] ⌋ σ 0 ( j ′ ) ∑ k ′ = 1 ⌊ C / [ d 2 , d 3 ] ⌋ σ 0 ( k ′ ) \sum_{d_1=1}^{\min(A,B)} \sum_{d_2=1}^{\min(A,C)} \sum_{d_3=1}^{\min(B,C)}\mu(d_2)\mu(d_1)\mu(d_3)
\sum_{i'=1}^{\left\lfloor A/[d_1,d_2]\right\rfloor} \sigma_0\left(i'\right)
\sum_{j'=1}^{\left\lfloor B/[d_1,d_3]\right\rfloor} \sigma_0\left(j'\right)
\sum_{k'=1}^{\left\lfloor C/[d_2,d_3]\right\rfloor} \sigma_0\left(k'\right)
d 1 = 1 ∑ m i n ( A , B ) d 2 = 1 ∑ m i n ( A , C ) d 3 = 1 ∑ m i n ( B , C ) μ ( d 2 ) μ ( d 1 ) μ ( d 3 ) i ′ = 1 ∑ ⌊ A / [ d 1 , d 2 ] ⌋ σ 0 ( i ′ ) j ′ = 1 ∑ ⌊ B / [ d 1 , d 3 ] ⌋ σ 0 ( j ′ ) k ′ = 1 ∑ ⌊ C / [ d 2 , d 3 ] ⌋ σ 0 ( k ′ )
考虑:
f ( n ) = ∑ i = 1 n σ 0 ( i ) = ∑ i = 1 n ∑ d = 1 n [ d ∣ n ] = ∑ d = 1 n ⌊ n d ⌋ \begin{aligned}
f(n)=&\sum_{i=1}^{n} \sigma_0\left(i\right)\\
=&\sum_{i=1}^{n} \sum_{d=1}^{n} [d\mid n]\\
=&\sum_{d=1}^{n} \left\lfloor \frac{n}{d}\right\rfloor
\end{aligned}
f ( n ) = = = i = 1 ∑ n σ 0 ( i ) i = 1 ∑ n d = 1 ∑ n [ d ∣ n ] d = 1 ∑ n ⌊ d n ⌋
f ( n ) f(n) f ( n ) 可以单次 O ( n ) O(\sqrt{n}) O ( n ) 求;考虑实际意义的话 f ( n ) f(n) f ( n ) 为 除数函数(即约数个数)前缀和,可以 O ( n ) O(n) O ( n ) 预处理。
代回原式:
∑ d 1 = 1 min ( A , B ) ∑ d 2 = 1 min ( A , C ) ∑ d 3 = 1 min ( B , C ) μ ( d 1 ) μ ( d 2 ) μ ( d 3 ) ⋅ f ( ⌊ A [ d 1 , d 2 ] ⌋ ) f ( ⌊ B [ d 1 , d 3 ] ⌋ ) f ( ⌊ C [ d 2 , d 3 ] ⌋ ) \sum_{d_1=1}^{\min(A,B)} \sum_{d_2=1}^{\min(A,C)}\sum_{d_3=1}^{\min(B,C)}\mu(d_1)\mu(d_2)\mu(d_3)\cdot
f\left(\left\lfloor \frac{A}{[d_1,d_2]}\right\rfloor\right)
f\left(\left\lfloor \frac{B}{[d_1,d_3]}\right\rfloor\right)
f\left(\left\lfloor \frac{C}{[d_2,d_3]}\right\rfloor\right)
d 1 = 1 ∑ m i n ( A , B ) d 2 = 1 ∑ m i n ( A , C ) d 3 = 1 ∑ m i n ( B , C ) μ ( d 1 ) μ ( d 2 ) μ ( d 3 ) ⋅ f ( ⌊ [ d 1 , d 2 ] A ⌋ ) f ( ⌊ [ d 1 , d 3 ] B ⌋ ) f ( ⌊ [ d 2 , d 3 ] C ⌋ )
搞了半天还是 O ( n 3 ) O(n^3) O ( n 3 ) 的复杂度,一分没有 。
考虑到我们算的是有序对 ( d 1 , d 2 , d 3 ) (d_1,d_2,d_3) ( d 1 , d 2 , d 3 ) 对答案的贡献,然后就 莫名其妙 地想到转化成图上三元环计数 。具体的:
每个点有点权,记 v a l u = μ ( u ) val_u=\mu(u) v a l u = μ ( u ) ;
( u , v ) (u,v) ( u , v ) 之间连边,边权 w u , v = [ u , v ] w_{u,v}=[u,v] w u , v = [ u , v ] ;
对于一个有序对 ( u , v , w ) (u,v,w) ( u , v , w ) 若两两不同则可以表示成图上一个三元环 ;
一个三元环 ( u , v , w ) (u,v,w) ( u , v , w ) 有贡献当且仅当 u ≤ min ( A , B ) ∧ v ≤ min ( A , C ) ∧ w ≤ min ( B , C ) u\le\min(A,B)\wedge v\le \min(A,C)\wedge w\le \min(B,C) u ≤ min ( A , B ) ∧ v ≤ min ( A , C ) ∧ w ≤ min ( B , C ) ,且其贡献为 v a l u v a l v v a l w ⋅ f ( ⌊ A w u , v ⌋ ) f ( ⌊ B w u , w ⌋ ) f ( ⌊ C w v , w ⌋ ) \displaystyle val_uval_vval_w\cdot f\left(\left\lfloor \frac{A}{w_{u,v}}\right\rfloor\right)f\left(\left\lfloor \frac{B}{w_{u,w}}\right\rfloor\right)f\left(\left\lfloor \frac{C}{w_{v,w}}\right\rfloor\right) v a l u v a l v v a l w ⋅ f ( ⌊ w u , v A ⌋ ) f ( ⌊ w u , w B ⌋ ) f ( ⌊ w v , w C ⌋ ) 。
考虑把一些没必要的点、边删掉,删除 v a l u = 0 val_u=0 v a l u = 0 的点,和 w u , v > max ( A , B , C ) w_{u,v}>\max(A,B,C) w u , v > max ( A , B , C ) 的边 ( u , v ) (u,v) ( u , v ) 。
建图 :
枚举边权 w w w ,边 ( u , v ) (u,v) ( u , v ) 满足 [ u , v ] = w , μ ( u ) ≠ 0 , μ ( v ) ≠ 0 [u,v]=w,\mu(u)\ne 0,\mu(v)\ne 0 [ u , v ] = w , μ ( u ) = 0 , μ ( v ) = 0 ,u , v u,v u , v 不能有平方因子,那么 w w w 也不能有,对 w w w 质因数分解,w = p 1 p 2 … p r w=p_1p_2\dots p_r w = p 1 p 2 … p r 需要满足 ∀ p \forall p ∀ p 有 p ∣ u p\mid u p ∣ u 或 p ∣ v p\mid v p ∣ v 。预处理因子,枚举子集即可。
实测 A , B , C = 1 0 5 A,B,C=10^5 A , B , C = 1 0 5 时边数只有 760741 760741 7 6 0 7 4 1 。
三元环计数有 O ( m m ) O(m\sqrt{m}) O ( m m ) 的方法(m m m 为边数,假设 n , m n,m n , m 同阶):
首先要对所有的无向边进行定向:对于任何一条边,从度数大的点连向度数小 的点,如果度数相同,从编号小的点连向编号大的点。此时这张图是一个有向无环图 。
之后枚举每一个点 u u u ,然后将 u u u 的所有相邻的点都标记上 「被 u u u 访问了」,然后再枚举 u u u 的相邻的点 v v v ,然后再枚举 v v v 的相邻的点 w w w ,如果 w w w 存在「被 u u u 访问了」的标记,那么 ( u , v , w ) (u,v,w) ( u , v , w ) 就是一个三元环了。
而且每个三元环只会被计算一次
证明
证明重定向后是无环图
假设存在有向环 p 1 → p 2 → ⋯ → p k → p 1 p_1\to p_2\to \dots \to p_k\to p_1 p 1 → p 2 → ⋯ → p k → p 1 ,那么有 deg 1 ≥ deg 2 ≥ ⋯ ≥ deg k ≥ deg 1 \deg_1\ge\deg_2\ge\dots\ge\deg_k\ge\deg_1 deg 1 ≥ deg 2 ≥ ⋯ ≥ deg k ≥ deg 1 ,即 deg 1 = deg 2 = ⋯ = deg k \deg_1=\deg_2=\dots=\deg_k deg 1 = deg 2 = ⋯ = deg k 。对于度数相同的点编号小的连大的,即 p 1 ≤ p 2 ≤ ⋯ ≤ p k ≤ p 1 p_1\le p_2\le \dots\le p_k\le p_1 p 1 ≤ p 2 ≤ ⋯ ≤ p k ≤ p 1 ,即 p 1 = p 2 = ⋯ = p k p_1=p_2=\dots=p_k p 1 = p 2 = ⋯ = p k ,然而不同的点编号显然不等,故假设不存在,因此该图无环
证明每个三元环之被算一次
每个三元环只可能是这样:u → v , u → w , v → w u\to v,u\to w,v\to w u → v , u → w , v → w (因为不存在有向环)。而这正好只会被 u u u 统计一次贡献。
证明时间复杂度为 O ( m m ) O(m\sqrt{m}) O ( m m )
首先遍历 u u u 相邻的点并打标记相当于遍历所有边,复杂的是 O ( n + m ) O(n+m) O ( n + m ) 的。
然后考虑 u u u 遍历到 v v v ,v v v 再访问 w w w 的复杂度,记 o u t v out_v o u t v 表示 v v v 的出边数量,转化为求 ∑ u → v o u t v \sum_{u\to v} out_v ∑ u → v o u t v
分讨 o u t v out_v o u t v 大小:
若 o u t v < m out_v<\sqrt{m} o u t v < m :因为 u → v u\to v u → v 有 O ( m ) O(m) O ( m ) 个,这样的复杂度 O ( m m ) O(m\sqrt{m}) O ( m m )
若 o u t v ≥ m out_v\ge\sqrt{m} o u t v ≥ m :因为 u → v u\to v u → v ,那么 deg u ≥ deg v ≥ m \deg_u\ge\deg_v\ge \sqrt{m} deg u ≥ deg v ≥ m 。考虑图中 deg > m \deg>\sqrt{m} deg > m 的点最多 m \sqrt{m} m 个。考虑 u u u 有 O ( m ) O(\sqrt{m}) O ( m ) 个,且 u u u 一次枚举 u → v → w u\to v\to w u → v → w 是 O ( m ) O(m) O ( m ) 的(边不会重复枚举),这样的复杂也是 O ( m m ) O(m\sqrt{m}) O ( m m )
故总复杂度 O ( m m ) O(m\sqrt{m}) O ( m m )
注意我们枚举到的三元环是无序 三元组,而统计的是有序 三元组,还要手动枚举 6 6 6 种情况。
注意还有 ( d 1 , d 2 , d 3 ) (d_1,d_2,d_3) ( d 1 , d 2 , d 3 ) 其中两个相同的情况,这是 O ( m ) O(m) O ( m ) 的,还有三个都相等的情况这是 O ( n ) O(n) O ( n ) 的。
CODE
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 #include <bits/stdc++.h> using namespace std;typedef long long ll;typedef pair<int ,int > pii;const int N = 200010 ;const int mod = 1e9 + 7 ;int gcd (int a, int b) { return !b ? a : gcd (b, a % b); } int p[N], mu[N], c[N], tot, f[N]; vector<int > divs[N]; vector<pii> e[N]; struct edge {int u, v, w;} E[2000000 ];pii vis[N]; int deg[N];int n, T, A, B, C, totE;bool v[N];void init (int n) { mu[1 ] = 1 ; f[1 ] = 1 ; for (int i = 2 ; i <= n; ++i) { if (!v[i]) p[++tot] = i, mu[i] = -1 , c[i] = 1 , f[i] = 2 , divs[i].push_back (i); for (int j = 1 ; j <= tot && p[j] * i <= n; ++j) { v[i * p[j]] = 1 ; divs[i * p[j]] = divs[i]; if (i % p[j] == 0 ) { mu[i * p[j]] = 0 ; c[i * p[j]] = c[i] + 1 ; f[i * p[j]] = f[i] / (c[i] + 1 ) * (c[i] + 2 ); break ; } divs[i * p[j]].push_back (p[j]); mu[i * p[j]] = -mu[i]; f[i * p[j]] = f[i] * 2 ; c[i * p[j]] = 1 ; } } for (int i = 1 ; i <= n; ++i) f[i] = (f[i] + f[i - 1 ]) % mod; } ll calc (int u, int v, int w, int uv, int uw, int vw) { if (u > min (A, B) || v > min (A, C) || w > min (B, C)) return 0 ; int t = mu[u] * mu[v] * mu[w]; ll r = (ll)f[A / uv] * f[B / uw] % mod * f[C / vw] % mod; return t == 1 ? r : mod - r; } void solve () { totE = 0 ; for (int i = 1 ; i <= n; ++i) e[i].clear (), deg[i] = 0 , vis[i] = pii (0 , 0 ); for (int k = 1 ; k <= n; ++k) if (mu[k] != 0 ) { int c = divs[k].size (), ful = (1 << c) - 1 ; vector<int > id (ful + 1 , 0 ) ; for (int sub = 0 ; sub <= ful; ++sub) { int u = 1 ; for (int i = 0 ; i < c; ++i) if ((sub >> i) & 1 ) u *= divs[k][i]; id[sub] = u; } for (int sub = 0 ; sub <= ful; ++sub) { for (int ssub = sub; true ; ssub = (ssub - 1 ) & sub) { int u = id[sub], v = id[ssub ^ ful]; if (u < v) { E[++totE] = edge{u, v, k}; ++deg[u], ++deg[v]; } if (ssub == 0 ) break ; } } } ll ans = 0 ; for (int i = 1 ; i <= totE; ++i) { int u = E[i].u, v = E[i].v, w = E[i].w; ans = (ans + calc (u, u, v, u, w, w)) % mod; ans = (ans + calc (u, v, u, w, u, w)) % mod; ans = (ans + calc (v, u, u, w, w, u)) % mod; ans = (ans + calc (v, v, u, v, w, w)) % mod; ans = (ans + calc (v, u, v, w, v, w)) % mod; ans = (ans + calc (u, v, v, w, w, v)) % mod; } for (int u = 1 ; u <= n; ++u) if (mu[u] != 0 ) { ans = (ans + calc (u, u, u, u, u, u)) % mod; } for (int i = 1 ; i <= totE; ++i) { if (deg[E[i].u] < deg[E[i].v] || (deg[E[i].u] == deg[E[i].v] && E[i].u < E[i].v)) swap (E[i].u, E[i].v); e[E[i].u].push_back (pii (E[i].v, E[i].w)); } for (int u = 1 ; u <= n; ++u) { for (int i = 0 ; i < (int )e[u].size (); ++i) vis[e[u][i].first] = pii (u, e[u][i].second); for (int i = 0 , v; i < (int )e[u].size (); ++i) { v = e[u][i].first; for (int j = 0 , w; j < (int )e[v].size (); ++j) { w = e[v][j].first; if (vis[w].first != u) continue ; int uv = e[u][i].second, vw = e[v][j].second, uw = vis[w].second; ans = (ans + calc (u, v, w, uv, uw, vw)) % mod; ans = (ans + calc (u, w, v, uw, uv, vw)) % mod; ans = (ans + calc (v, u, w, uv, vw, uw)) % mod; ans = (ans + calc (v, w, u, vw, uv, uw)) % mod; ans = (ans + calc (w, u, v, uw, vw, uv)) % mod; ans = (ans + calc (w, v, u, vw, uw, uv)) % mod; } } } cout << ans << endl; } void rmain () { cin >> A >> B >> C; n = max (max (A, B), C); solve (); } int main () { init (N - 1 ); cin >> T; while (T--) rmain (); return 0 ; }