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 }
CF809E

 

posted @ 2019-04-06 10:21  mizu164  阅读(256)  评论(0编辑  收藏  举报