zoukankan      html  css  js  c++  java
  • CF1540B-Tree Array

    题目链接
    思路
    对于这种期望题第一反应就是把每一对逆序对独立出来计算他们的贡献,那么对于一对逆序对((j,i),j>i)就需要考虑在每一种根下面的情况。将逆序对((j,i))在每一种根下面所有的情况加起来除以(n),就是逆序对((j,i))对总期望的贡献值。要让逆序对有贡献,那么就必须要让(j)出现在(i)的前面,就是求(j)出现在(i)前面的概率。
    假设现在(i,j)(LCA)(p),那么就有(p-i)(p-j)的两条路径。我们可以发现在选择(p-i,p-j)这两条路径之外的点时对这个概率并无影响。所以只要考虑以(p)为LCA的情况下先到达(j)的概率。
    (f[x][y]:)表示距离从(p)(i)路径上还剩下x个点,(p)(j)路径上还剩下(y)个点的概率值。
    转移方程即为
    (f[x][y]=(f[x-1][y]+f[x][y-1])/2)
    表示可能选择的是路径(p-i)上的点的概率和路径(p-j)上的点的概率。
    那么因为要计算逆序对((j,i))的情况,初始情况下要设置(f[1...n][0]=1)

    所以就需要枚举每个根,然后再去计算这种根的情况下的概率值。最后把所有的概率值加起来/n即可。

    代码

    vector<int> e[N];
    int fa[N][10];
    LL f[N][N];
    int depth[N];
    int n;
    
    LL kpow(LL a, LL n) {
        LL res = 1;
        while(n) {
            if(n & 1) res = res * a % mod;
            n >>= 1;
            a = a * a % mod;
        }
        return res;
    }
    
    void bfs(int s) {
        memset(depth, 0, sizeof depth);
        queue<int> q;
        q.push(s);
        depth[s] = 1;
        while(!q.empty()) {
            int u = q.front(); q.pop();
            for(auto v : e[u]) {
                if(!depth[v]) {
                    depth[v] = depth[u] + 1;
                    fa[v][0] = u;
                    for(int i = 1; i < 9; i++) {
                        fa[v][i] = fa[fa[v][i - 1]][i - 1];
                    }
                    q.push(v);
                }
            }
        }
    }
    
    int lca(int a, int b, int u) {
        if(depth[a] < depth[b]) swap(a, b);
        for(int i = 8; i >= 0; i--) {
            if(depth[fa[a][i]] >= depth[b]) {
                a = fa[a][i];
            }
        }
        if(a == b) return a;
        for(int i = 8; i >= 0; i--) {
            if(fa[a][i] != fa[b][i]) {
                a = fa[a][i];
                b = fa[b][i];
            }
        }
        return fa[a][0];
    }
    
    LL calc(int u) {
        memset(fa, 0, sizeof fa);
        depth[u] = 1;
        bfs(u);
        LL res = 0;
        for(int i = 1; i <= n; i++) {
            for(int j = i + 1; j <= n; j++) {
                int p = lca(i, j, u);
                res = (res + f[depth[i] - depth[p]][depth[j] - depth[p]]) % mod;
            }
        }
        return res;
    }
    
    void solve() {
        
        scanf("%d", &n);
        for(int i = 1; i < n; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            e[u].push_back(v);
            e[v].push_back(u);
        }
        for(int i = 1; i <= n; i++) {
            f[i][0] = 1;
        }
        LL tmp = kpow(2, mod - 2);
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= n; j++) {
                f[i][j] = (f[i - 1][j] + f[i][j - 1]) % mod * tmp % mod;
            }
        }
    
        LL res = 0;
        for(int i = 1; i <= n; i++) {
            res = (res + 1LL * calc(i) * kpow(n, mod - 2) % mod) % mod;
        }
        printf("%lld
    ", res);
    }
    
  • 相关阅读:
    [转]html之file标签 --- 图片上传前预览 -- FileReader
    常用正则表达式
    c# color 颜色代码
    WebForm 母版页使用
    iframe同域自适应问题
    完整版AJAX
    AJAX基础
    jQuery 小特效【文本框折叠隐藏,展开显示】【下拉菜单】【颜色渐变】【弹窗+遮罩】
    JQuery中的Dom操作和事件
    LINQ 【增、删、改、查】数据绑定
  • 原文地址:https://www.cnblogs.com/ZX-GO/p/14966851.html
Copyright © 2011-2022 走看看