• 【codeforces 791D】 Bear and Tree Jumps


    【题目链接】:http://codeforces.com/contest/791/problem/D

    【题意】

    你可以从树上的节点一次最多走k条边。
    (称为跳一次);
    树为无权树;
    然后问你任意两点之间的条的次数的和为多少;

    【题解】

    如果k=1的话;
    问题就是求任意两点之间的距离的和了;
    这个可以在O(N)的复杂度下搞出来;

    枚举每一条边;
    看这条边左边的点的数目和右边的点的数目分别为多少->num1和num2
    num1*num2就是经过这条边的路径个数;
    累加所有的边的这个值就是任意两点之间的距离了;
    但是对于k>1的情况有点不同;
    可以假设上面求的k=1的情况的答案为S

    k>2的答案应该为
    (S+∑f(l,k))/k;
    这里f(l,k)指的是某个路径长度为l,然后让他能够被k整除还要加上几.
    f(10, 3) = 2, f(11, 3) = 1, f(12, 3) = 0.
    这里的∑f(l,k)
    也能在O(N)*K^2的复杂度内搞出来;
    具体的
    设某条路径的长度为k;
    然后令这条路径对k求余结果为x
    比如
    有200条边它们的长度对3求余的结果都是1
    则这每条边都要加上2才能被3整除;
    即结果加上200*2;
    然后对于树上的任意两点之间的距离(x,y);
    =dep[x]+dep[y]-2*dep[t];
    t是它们的最近公共祖先.
    然后O(K^2)枚举这条边两端的端点的深度对k的求余结果i和j
    i+j-2*dep[now]就是深度%k的结果为i的节点和深度%k的结果为j的节点的距离了.
    然后%k得到dis;
    用k减去dis再%k就是长度%k为dis的路径,每条路径需要额外加上的距离了.
    按照这个方法搞出∑f(l,k)就好;


    【完整代码】

    #include <bits/stdc++.h>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define LL long long
    #define rep1(i,a,b) for (int i = a;i <= b;i++)
    #define rep2(i,a,b) for (int i = a;i >= b;i--)
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define rei(x) scanf("%d",&x)
    #define rel(x) scanf("%lld",&x)
    #define ref(x) scanf("%lf",&x)
    
    typedef pair<int, int> pii;
    typedef pair<LL, LL> pll;
    
    const int dx[9] = { 0,1,-1,0,0,-1,-1,1,1 };
    const int dy[9] = { 0,0,0,-1,1,-1,1,-1,1 };
    const double pi = acos(-1.0);
    const int N = 20e4+100;
    
    vector <int> G[N];
    int n,k;
    LL sum[N],a[N][5+2],ans;
    
    void in()
    {
        rei(n), rei(k);
        rep1(i, 1, n - 1)
        {
            int x, y;
            rei(x), rei(y);
            G[x].push_back(y),G[y].push_back(x);
        }
    }
    
    void dfs(int x, int fa,int dep)
    {
        a[x][dep%k] = sum[x] = 1;
        for (int y : G[x])
        {
            if (y == fa) continue;
            dfs(y, x, dep + 1);
            rep1(i,0,k-1)
                rep1(j, 0, k-1)
                {
                    int dis = ((i + j) % k - ((dep * 2) % k) + k) % k;
                    int t = (k - dis + k) % k;
                    ans += t*a[x][i] * a[y][j];
                }
            rep1(i, 0, k - 1)
                a[x][i] += a[y][i];
            sum[x] += sum[y];
            ans += (n - sum[y])*sum[y];
        }
    }
    
    void o()
    {
        cout << ans / k << endl;
    }
    
    int main()
    {
        //freopen("F:\rush.txt", "r", stdin);
        in();
        dfs(1, 0,0);
        o();
        //printf("
    %.2lf sec 
    ", (double)clock() / CLOCKS_PER_SEC);
        return 0;
    }
  • 相关阅读:
    作为一个iOS Developer 为什么我不用Swift?
    闲着蛋疼没事干,写个Mac端的Kcptun Client管理器
    macOS 10.12 解决模拟器不流畅的一段命令行
    「iOS造轮子」之UIButton 用Block响应事件
    Java spring security 开发企业级权限管理系统
    mysql性能优化30条
    Django高级实战-开发企业级问答网站(二)
    Django高级实战 开发企业级问答网站 (一)
    微信小程序云开发之云音乐
    flask全栈开发11 memcached,redis教程:CSRF攻击
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626541.html
Copyright © 2020-2023  润新知