CF809E Surprise me!
题目链接:洛谷 codeforces
这道题太神仙了!推了好久式子。。。
首先有一个很好的结论。
$$\varphi(ij)=\frac{\varphi(i)\varphi(j)gcd(i,j)}{\varphi(gcd(i,j))}$$
然后就可以开始lu了。
为了方便,我们设$a_j=i$则$p_i=j$
$$Ans*n*(n-1)=\sum_{i=1}^n\sum_{j=1}^n\varphi(ij)dis(p_i,p_j)$$
$$=\sum_{d=1}^n\frac{d}{\varphi(d)}\sum_{i=1}^n\sum_{j=1}^n\varphi(i)\varphi(j)dis(p_i,p_j)[gcd(i,j)=d]$$
上莫比乌斯反演
$$f(d)=\sum_{i=1}^n\sum_{j=1}^n\varphi(i)\varphi(j)dis(p_i,p_j)[gcd(i,j)=d]$$
$$F(d)=\sum_{d|i}\sum_{d|j}\varphi(i)\varphi(j)dis(p_i,p_j)$$
$$f(d)=\sum_{d|T}\mu(\frac{T}{d})F(T)$$
代入就是
$$Ans*n*(n-1)=\sum_{d=1}^n\frac{d}{\varphi(d)}f(d)$$
$$=\sum_{T=1}^nF(T)\sum_{d|T}\frac{d\mu(\frac{T}{d})}{\varphi(d)}$$
后面那个可以调和级数$O(n\log n)$预处理,前面那个发现就是选出一些点两两计算$\varphi(a_i)\varphi(a_j)dis(i,j)$,就是虚树dp了。
我们设$dp_x$为以$x$为根的子树的答案。考虑扩展一个儿子$v$的时候,除了加上$dp_v$,还有跨越$(x,v)$的贡献$w(x,v)$。设$(x,v)$的边权为$w$.
设点权$b_x=\varphi(a_x)[T|a_x]$
$$w(x,v)=\sum_{i\in X}\sum_{j\in V}b_ib_jdis(i,j)$$
$$=(\sum_{i\in X}b_idis(x,i))(\sum_{j\in V}b_j)+w(\sum_{i\in X}b_i)(\sum_{j\in V}b_j)+(\sum_{i\in X}b_i)(\sum_{j\in V}b_jdis(v,j))$$
然后设
$$f_x=\sum_{i\in X}b_idis(x,i)$$
$$s_x=\sum_{i\in X}b_i$$
所以
$$dp_x+=dp_v+f_xs_v+ws_xs_v+s_xf_v$$
$$f_x+=f_v+ws_v$$
$$s_x+=s_v$$
初值:$dp_x=f_x=0,s_x=b_x$,然后就做完了
我们发现虚树的总点数也是调和级数$O(n\log n)$,所以是没问题的
(lca保险起见还是rmq吧,但是这道题连倍增都能过,就懒得写了)
1 #include<bits/stdc++.h> 2 #define Rint register int 3 using namespace std; 4 typedef long long LL; 5 const int N = 200003, mod = 1e9 + 7; 6 int n, a[N], p[N], head[N], to[N << 1], nxt[N << 1]; 7 inline int add(int a, int b){int res = a + b; if(res >= mod) res -= mod; return res;} 8 inline int dec(int a, int b){int res = a - b; if(res < 0) res += mod; return res;} 9 inline void addedge(int a, int b){ 10 static int cnt = 0; 11 to[++ cnt] = b; nxt[cnt] = head[a]; head[a] = cnt; 12 } 13 bool notp[N]; 14 int inv[N], pri[N], tot, phi[N], mu[N], pre[N]; 15 inline void init(){ 16 inv[0] = 0; inv[1] = 1; 17 for(Rint i = 2;i <= n;i ++) inv[i] = (LL) (mod - mod / i) * inv[mod % i] % mod; 18 notp[0] = notp[1] = true; 19 phi[0] = mu[0] = 0; phi[1] = mu[1] = 1; 20 for(Rint i = 2;i <= n;i ++){ 21 if(!notp[i]){pri[++ tot] = i; mu[i] = -1; phi[i] = i - 1;} 22 for(Rint j = 1;j <= tot && i * pri[j] <= n;j ++){ 23 notp[i * pri[j]] = true; 24 if(i % pri[j]){ 25 phi[i * pri[j]] = phi[i] * (pri[j] - 1); 26 mu[i * pri[j]] = -mu[i]; 27 } else { 28 phi[i * pri[j]] = phi[i] * pri[j]; 29 mu[i * pri[j]] = 0; 30 break; 31 } 32 } 33 } 34 for(Rint i = 1;i <= n;i ++) 35 for(Rint j = i;j <= n;j += i) 36 pre[j] = add(pre[j], add((LL) i * inv[phi[i]] % mod * mu[j / i], mod)); 37 } 38 int dep[N], fa[N], siz[N], wson[N], top[N], dfn[N], tim; 39 inline void dfs1(int x){ 40 siz[x] = 1; 41 for(Rint i = head[x];i;i = nxt[i]) 42 if(to[i] != fa[x]){ 43 dep[to[i]] = dep[x] + 1; 44 fa[to[i]] = x; 45 dfs1(to[i]); 46 siz[x] += siz[to[i]]; 47 if(siz[to[i]] > siz[wson[x]]) wson[x] = to[i]; 48 } 49 } 50 inline void dfs2(int x, int topf){ 51 top[x] = topf; dfn[x] = ++ tim; 52 if(wson[x]) dfs2(wson[x], topf); 53 for(Rint i = head[x];i;i = nxt[i]) 54 if(to[i] != fa[x] && to[i] != wson[x]) 55 dfs2(to[i], to[i]); 56 } 57 inline int LCA(int x, int y){ 58 while(top[x] != top[y]){ 59 if(dep[top[x]] < dep[top[y]]) swap(x, y); 60 x = fa[top[x]]; 61 } 62 return dep[x] < dep[y] ? x : y; 63 } 64 int nod[N], k, s[N], tt; 65 bool spe[N]; 66 vector<int> E[N]; 67 inline void build(int x){ 68 int lca = LCA(s[tt], x); 69 if(tt == 1 || lca == s[tt]){s[++ tt] = x; return;} 70 while(tt > 1 && dfn[s[tt - 1]] >= dfn[lca]){ 71 E[s[tt - 1]].push_back(s[tt]); 72 -- tt; 73 } 74 if(lca != s[tt]){ 75 E[lca].push_back(s[tt]); 76 s[tt] = lca; 77 } 78 s[++ tt] = x; 79 } 80 LL G[N], F[N], S[N]; 81 int ans; 82 inline void dp(int x){ 83 S[x] = spe[x] ? phi[a[x]] : 0; F[x] = G[x] = 0; 84 for(int v : E[x]){ 85 dp(v); 86 int w = dep[v] - dep[x]; 87 G[x] = add(G[v], add(add(G[x], S[v] * add(w * S[x] % mod, F[x]) % mod), S[x] * F[v] % mod)); 88 S[x] = add(S[x], S[v]); 89 F[x] = add(F[x], add(F[v], S[v] * w % mod)); 90 } 91 E[x].clear(); 92 spe[x] = false; 93 } 94 inline int calc(int T){ 95 k = 0; 96 for(Rint i = T;i <= n;i += T) 97 nod[++ k] = p[i]; 98 sort(nod + 1, nod + k + 1, [](int x, int y) -> bool {return dfn[x] < dfn[y];}); 99 s[tt = 1] = 1; 100 for(Rint i = 1;i <= k;i ++){ 101 if(nod[i] != 1) build(nod[i]); 102 spe[nod[i]] = true; 103 } 104 while(tt){ 105 E[s[tt - 1]].push_back(s[tt]); 106 -- tt; 107 } 108 dp(1); 109 return G[1] * pre[T] % mod; 110 } 111 int main(){ 112 scanf("%d", &n); 113 init(); 114 for(Rint i = 1;i <= n;i ++){ 115 scanf("%d", a + i); 116 p[a[i]] = i; 117 } 118 for(Rint i = 1;i < n;i ++){ 119 int a, b; 120 scanf("%d%d", &a, &b); 121 addedge(a, b); addedge(b, a); 122 } 123 dfs1(1); dfs2(1, 1); 124 for(Rint i = 1;i <= n;i ++) ans = add(ans, calc(i)); 125 printf("%d\n", (LL) ans * inv[n] % mod * inv[n - 1] % mod * 2 % mod); 126 }