E. Surprise me!(莫比乌斯反演 + 虚树 DP)

12 篇文章 0 订阅

E. Surprise me!

∑ i = 1 n ∑ j = 1 n ϕ ( a i × a j ) d ( i , j ) 设 p a i = i ∑ i = 1 n ∑ j = 1 n ϕ ( i × j ) d ( p i , p j ) ∑ i = 1 n ∑ j = 1 n ϕ ( i ) ϕ ( j ) ϕ ( gcd ⁡ ( i , j ) ) × gcd ⁡ ( i , j ) × d ( p i , p j ) ∑ d = 1 n d ϕ ( d ) ∑ i = 1 n d ∑ j = 1 n d ϕ ( i d ) ϕ ( j d ) × d ( p i d , p j d ) [ gcd ⁡ ( i , j ) = 1 ] ∑ d = 1 n d ϕ ( d ) ∑ k = 1 n d μ ( k ) ∑ i = 1 n k d ∑ j = 1 n k d ϕ ( i k d ) ϕ ( j k d ) × d ( p i k d , p j k d ) T = k d ∑ T = 1 n ( ∑ i = 1 n T ∑ j = 1 n T ϕ ( i T ) ϕ ( j T ) × d ( p i T , p j T ) ) ∑ d ∣ T d ϕ ( d ) × μ ( T d ) \sum_{i = 1} ^{n} \sum_{j = 1} ^{n} \phi(a_i \times a_j) d(i, j)\\ 设p_{a_i} = i\\ \sum_{i = 1} ^{n} \sum_{j = 1} ^{n} \phi(i \times j) d(p_i, p_j)\\ \sum_{i = 1} ^{n} \sum_{j = 1} ^{n} \frac{\phi(i) \phi(j)}{\phi(\gcd(i, j))} \times \gcd(i, j) \times d(p_i, p_j)\\ \sum_{d = 1} ^{n} \frac{d}{\phi(d)} \sum_{i = 1} ^{\frac{n}{d}} \sum_{j = 1} ^{\frac{n}{d}} \phi(id) \phi(jd) \times d(p_{id}, p_{jd})[\gcd(i, j) = 1]\\ \sum_{d = 1} ^{n} \frac{d}{\phi(d)} \sum_{k = 1} ^{\frac{n}{d}} \mu(k) \sum_{i = 1} ^{\frac{n}{kd}} \sum_{j = 1} ^{\frac{n}{kd}} \phi(ikd) \phi(jkd) \times d(p_{ikd}, p_{jkd})\\ T = kd\\ \sum_{T = 1} ^{n} \left(\sum_{i = 1} ^{\frac{n}{T}} \sum_{j = 1} ^{\frac{n}{T}} \phi(iT) \phi(jT) \times d(p_{iT}, p_{jT}) \right) \sum_{d \mid T} \frac{d}{\phi(d)} \times \mu(\frac{T}{d})\\ i=1nj=1nϕ(ai×aj)d(i,j)pai=ii=1nj=1nϕ(i×j)d(pi,pj)i=1nj=1nϕ(gcd(i,j))ϕ(i)ϕ(j)×gcd(i,j)×d(pi,pj)d=1nϕ(d)di=1dnj=1dnϕ(id)ϕ(jd)×d(pid,pjd)[gcd(i,j)=1]d=1nϕ(d)dk=1dnμ(k)i=1kdnj=1kdnϕ(ikd)ϕ(jkd)×d(pikd,pjkd)T=kdT=1ni=1Tnj=1Tnϕ(iT)ϕ(jT)×d(piT,pjT)dTϕ(d)d×μ(dT)

我们设 h ( n ) = ∑ d ∣ n d ϕ ( d ) × μ ( n d ) h(n) = \sum\limits_{d \mid n} \frac{d}{\phi(d)} \times \mu(\frac{n}{d}) h(n)=dnϕ(d)d×μ(dn),应该是个积性函数吧,但是 O ( n log ⁡ n ) O(n \log n) O(nlogn)方便,,,

考虑如何求解 F ( T ) = ∑ i = 1 n T ∑ j = 1 n T ϕ ( i T ) ϕ ( j T ) × d ( p i T , p j T ) F(T) = \sum\limits_{i = 1} ^{\frac{n}{T}} \sum\limits_{j = 1} ^{\frac{n}{T}} \phi(iT) \phi(jT) \times d(p_{iT}, p_{jT}) F(T)=i=1Tnj=1Tnϕ(iT)ϕ(jT)×d(piT,pjT),为了方便,简化为 T = 1 T = 1 T=1的情况。

∑ i = 1 n ∑ j = 1 n ϕ ( i ) ϕ ( j ) × d ( p i , p j ) = ∑ i = 1 n ϕ ( i ) ∑ j = 1 n ϕ ( j ) × d ( p i , p j ) \sum\limits_{i = 1} ^{n} \sum\limits_{j = 1} ^{n} \phi(i) \phi(j) \times d(p_i, p_j) = \sum\limits_{i = 1} ^{n} \phi(i)\sum\limits_{j = 1} ^{n} \phi(j) \times d(p_i, p_j) i=1nj=1nϕ(i)ϕ(j)×d(pi,pj)=i=1nϕ(i)j=1nϕ(j)×d(pi,pj)

在这里插入图片描述

考虑信息在两棵子树上合并, ∑ i ∈ U w ( i ) ∑ j ∈ V w ( j ) × d ( i × j ) = ∑ i ∈ U w ( i ) ∑ j ∈ V w ( j ) × ( d ( i , u ) + l e n + d ( v , j ) ) \sum\limits_{i \in U} w(i) \sum\limits_{j \in V} w(j) \times d(i \times j) = \sum\limits_{i \in U} w(i) \sum\limits_{j \in V} w(j) \times (d(i, u) + len + d(v, j)) iUw(i)jVw(j)×d(i×j)=iUw(i)jVw(j)×(d(i,u)+len+d(v,j))
∑ i ∈ U w ( i ) × d ( i , u ) ∑ j ∈ V w ( j ) + l e n ∑ i ∈ U w ( i ) ∑ j ∈ V w ( j ) + ∑ i ∈ U w ( i ) ∑ j ∈ V w ( j ) × d ( v , j ) \sum_{i \in U} w(i) \times d(i, u) \sum_{j \in V} w(j) + len \sum_{i \in U} w(i) \sum_{j \in V} w(j) + \sum_{i \in U} w(i) \sum_{j \in V} w(j) \times d(v, j)\\ iUw(i)×d(i,u)jVw(j)+leniUw(i)jVw(j)+iUw(i)jVw(j)×d(v,j)
于是设 f ( x ) = ∑ i ∈ X w ( i ) × d ( i , x ) , g ( x ) = ∑ j ∈ X w ( j ) f(x) = \sum\limits_{i \in X} w(i) \times d(i, x), g(x) = \sum\limits_{j \in X} w(j) f(x)=iXw(i)×d(i,x),g(x)=jXw(j),于是有上式子为 f ( U ) × g ( V ) + l e n × g ( U ) × g ( v ) + g ( U ) × f ( V ) f(U) \times g(V) + len \times g(U) \times g(v) + g(U) \times f(V) f(U)×g(V)+len×g(U)×g(v)+g(U)×f(V)

同样地,对于 f ( x ) , g ( x ) f(x), g(x) f(x),g(x)的转移也比较简单, f ( U ) = f ( U ) + l e n × g ( V ) + f ( V ) , g ( U ) = g ( U ) + g ( V ) f(U) = f(U) + len \times g(V) + f(V), g(U) = g(U) + g(V) f(U)=f(U)+len×g(V)+f(V),g(U)=g(U)+g(V)

那么 F ( U ) = F ( U ) + F ( V ) + ( f ( U ) × g ( V ) + l e n × g ( U ) × g ( v ) + g ( U ) × f ( V ) ) F(U) = F(U) + F(V) + \left(f(U) \times g(V) + len \times g(U) \times g(v) + g(U) \times f(V)\right) F(U)=F(U)+F(V)+(f(U)×g(V)+len×g(U)×g(v)+g(U)×f(V)),最后即可得到我们所要的答案。

上面的计算可以用虚树求解,这道题的整体复杂度 O ( n log ⁡ 2 n ) O(n \log ^ 2 n) O(nlog2n)

#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 10, mod = 1e9 + 7;

int head[N], to[N << 1], nex[N << 1], cnt = 1;

int son[N], sz[N], fa[N], dep[N], id[N], top[N], tot;

int n, a[N], p[N], stk[N], prime[N], phi[N], mu[N], h[N], inv[N], num, tp;

int f[N], g[N], F[N], w[N];

vector< pair<int, int> > G[N];

bool st[N];

inline int Add(int x, int y) {
  return x + y < mod ? x + y : x + y - mod;
}

inline int Sub(int x, int y) {
  return x >= y ? x - y : x - y + mod;
}

void init() {
  phi[1] = mu[1] = inv[1] = 1;
  for (int i = 2; i < N; i++) {
    inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
    if (!st[i]) {
      prime[++num] = i;
      mu[i] = -1;
      phi[i] = i - 1;
    }
    for (int j = 1; j <= num && 1ll * i * prime[j] < N; j++) {
      st[i * prime[j]] = 1;
      if (i % prime[j] == 0) {
        phi[i * prime[j]] = phi[i] * prime[j];
        break;
      }
      mu[i * prime[j]] = -mu[i];
      phi[i * prime[j]] = phi[i] * (prime[j] - 1);
    }
  }
  for (int i = 1; i < N; i++) {
    for (int j = i; j < N; j += i) {
      if (mu[j / i]) {
        if (mu[j / i] == -1) {
          h[j] = Sub(h[j], 1ll * i * inv[phi[i]] % mod);
        }
        else {
          h[j] = Add(h[j], 1ll * i * inv[phi[i]] % mod);
        }
      }
    }
  }
}

void add(int x, int y) {
  to[cnt] = y;
  nex[cnt] = head[x];
  head[x] = cnt++;
}

int lca(int u, int v) {
  while (top[u] != top[v]) {
    if (dep[top[u]] < dep[top[v]]) {
      swap(u, v);
    }
    u = fa[top[u]];
  }
  return dep[u] < dep[v] ? u : v;
}

void dfs1(int rt, int f) {
  sz[rt] = 1, dep[rt] = dep[f] + 1, fa[rt] = f, id[rt] = ++tot;
  for (int i = head[rt]; i; i = nex[i]) {
    if (to[i] == f) {
      continue;
    }
    dfs1(to[i], rt);
    sz[rt] += sz[to[i]];
    if (!son[rt] || sz[to[i]] > sz[son[rt]]) {
      son[rt] = to[i];
    }
  }
}

void dfs2(int rt, int tp) {
  top[rt] = tp;
  if (!son[rt]) {
    return; 
  }
  dfs2(son[rt], tp);
  for (int i = head[rt]; i; i = nex[i]) {
    if (to[i] == fa[rt] || to[i] == son[rt]) {
      continue;
    }
    dfs2(to[i], to[i]);
  }
}

bool cmp(int a, int b) {
  return id[a] < id[b];
}

void dp(int u, int fa) {
  f[u] = 0, g[u] = w[u], F[u] = 0;
  for (auto to : G[u]) {
    int len = to.second, v = to.first;
    if (v == fa) {
      continue;
    }
    dp(v, u);
    F[u] = Add(Add(F[u], F[v]), Add(Add(1ll * f[u] * g[v] % mod, 1ll * len * g[u] % mod * g[v] % mod), 1ll * g[u] * f[v] % mod));
    f[u] = Add(Add(f[u], f[v]), 1ll * len * g[v] % mod);
    g[u] = Add(g[u], g[v]);
  }
  G[u].clear();
}

void insert(int rt) {
  if (tp == 1) {
    if (rt != 1) {
      stk[++tp] = rt;
    }
    return ;
  }
  int lc = lca(rt, stk[tp]);
  if (lc == stk[tp]) {
    stk[++tp] = rt;
    return ;
  }
  while (tp > 1 && id[stk[tp - 1]] >= id[lc]) {
    int u = stk[tp - 1], v = stk[tp];
    G[u].push_back({v, dep[v] - dep[u]});
    tp--;
  }
  if (stk[tp] != lc) {
    int u = lc, v = stk[tp];
    G[u].push_back({v, dep[v] - dep[u]});
    stk[tp] = lc;
  }
  stk[++tp] = rt;
}

int calc(int T) {
  int tot = 0;
  for (int i = T; i <= n; i += T) {
    a[++tot] = p[i];
    w[p[i]] = phi[i];
  }
  sort(a + 1, a + 1 + tot, cmp);
  stk[tp = 1] = 1;
  for (int i = 1; i <= tot; i++) {
    insert(a[i]);
  }
  while (tp > 1) {
    int u = stk[tp - 1], v = stk[tp];
    G[u].push_back({v, dep[v] - dep[u]});
    tp--;
  }
  dp(1, 0);
  for (int i = 1; i <= tot; i++) {
    w[a[i]] = 0;
  }
  return F[1];
}

int main() {
  // freopen("in.txt", "r", stdin);
  // freopen("out.txt", "w", stdout);
  init();
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) {
    scanf("%d", &a[i]);
    p[a[i]] = i;
  }
  for (int i = 1, u, v; i < n; i++) {
    scanf("%d %d", &u, &v);
    add(u, v);
    add(v, u);
  }
  dfs1(1, 0);
  dfs2(1, 1);
  int ans = 0;
  for (int i = 1; i <= n; i++) {
    ans = Add(ans, 1ll * calc(i) * h[i] % mod);
  }
  printf("%lld\n", 1ll * ans * inv[n] % mod * inv[n - 1] % mod * 2 % mod);
  return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值