CF1540B Tree Array

https://www.luogu.com.cn/problem/CF1540B

VP的时候卡题了QWQ
考虑期望的线性性,可以考虑每一对逆序对 a > b a>b a>b的概率
求和就是期望

所以肯定是要先枚举两个点 a > b a>b a>b,然后还要枚举第一个点

考虑对于一个确定的根,怎么计算 a > b a>b a>b的概率
转换一下可以发现如果联通块拓展的点不在a,b路径上时其实是不会对他们之间的概率产生影响的
问题就变成了从根走,先到a的概率
注意到lca以上的时候会使他们两个点距离同时减1,不用管,只用考虑lca到他们两个的距离就可以了
f [ i ] [ j ] 表 示 距 离 a 为 i , b 为 j 的 概 率 显 然 f [ i ] [ j ] = f [ i − 1 ] [ j ] + f [ i ] [ j − 1 ] 2 f[i][j]表示距离a为i,b为j的 概率 \\ 显然f[i][j]=\frac{f[i-1][j]+f[i][j-1]}{2} f[i][j]aibjf[i][j]=2f[i1][j]+f[i][j1]
预处理之后直接用即可
code:

#include<bits/stdc++.h>
#define N 450
#define mod 1000000007
using namespace std;
struct edge {
    int v, nxt;
} e[N << 1];
int p[N], eid;
void init() {
    memset(p, -1, sizeof p);
    eid = 0;
}
void insert(int u, int v) {
    e[eid].v = v;
    e[eid].nxt = p[u];
    p[u] = eid ++;
}
int qpow(int x, int y) {
    int ret = 1;
    for(; y; y >>= 1, x = 1ll * x * x % mod) if(y & 1) ret = 1ll * ret * x % mod;
    return ret;
}
int n, fa[N][10], dep[N], f[N][N];
const int inv2 = (mod + 1) / 2;
void dfs(int u, int ff) {
    fa[u][0] = ff, dep[u] = dep[ff] + 1;
    for(int i = 1; i <= 8; i ++) fa[u][i] = fa[fa[u][ i - 1]][i - 1];
    for(int i = p[u]; i + 1; i = e[i].nxt) {
        int v = e[i].v;
        if(v == ff) continue;
        dfs(v, u);
    }
}
int LCA(int x, int y) {
    if(dep[x] < dep[y]) swap(x, y);
    for(int i = 8; i >= 0; i --) if(dep[fa[x][i]] >= dep[y]) x = fa[x][i];
    if(x == y) return x;
    for(int i = 8; i >= 0; i --) if(fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
    return fa[x][0];
}
int main() {
    init();
    scanf("%d", &n);
    for(int i = 1; i < n; i ++) {
        int u, v;
        scanf("%d%d", &u, &v);
        insert(u, v), insert(v, u);
    }
    for(int i = 1; i <= n; i ++) f[0][i] = 1;
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= n; j ++)
            f[i][j] = 1ll * (f[i - 1][j] + f[i][j - 1]) * inv2 % mod;
    int ans = 0;
    for(int u = 1; u <= n; u ++) {
        dfs(u, 0);
        for(int i = 1; i <= n; i ++)
            for(int j = 1; j < i; j ++) {
                int lca = LCA(i, j);
                ans = (ans + f[dep[i] - dep[lca]][dep[j] - dep[lca]]) % mod;
            }
    }
    printf("%d", 1ll * ans * qpow(n, mod - 2) % mod);
    return 0;
}
posted @ 2021-09-02 20:38  lahlah  阅读(23)  评论(0编辑  收藏  举报