zoukankan      html  css  js  c++  java
  • 【BJOI2018】求和

    题目描述

    $master$ 对树上的求和非常感兴趣。他生成了一棵有根树,并且希望多次询问这棵树上一段路径上所有节点深度的$k$次方和,而且每次的$k$可能是不同的。此处节点深度的定义是这个节点到根的路径上的边数。他把这个问题交给了$pupil$,但$pupil$ 并不会这么复杂的操作,你能帮他解决吗?

    输入输出格式

    输入格式:

    第一行包含一个正整数n,表示树的节点数。

    之后n-1行每行两个空格隔开的正整数i, j ,表示树上的一条连接点$i$和点$j$的边。

    之后一行一个正整数,表示询问的数量。

    之后每行三个空格隔开的正整数i, j, k,表示询问从点i到点j的路径上所有节点深度的k次方和。由于这个结果可能非常大,输出其对998244353取模的结果。

    树的节点从1开始标号,其中1号节点为树的根。

    输出格式:

    对于每组数据输出一行一个正整数表示取模后的结果。

    思路

    对$k=1...50$全部预处理出来,然后就是LCA模板题了

    #include <bits/stdc++.h>
    using namespace std;
    const long long maxn = 300000 + 10;
    const long long MOD =  998244353;
    long long n,m,dep[maxn],father[maxn][25],d[maxn][51];
    vector<long long> edges[maxn];
    inline long long quickpow(long long x,long long y) {
        long long ans = 1;
        for (;y;y >>= 1,x = x*x%MOD) if (y&1) ans = ans*x%MOD;
        return ans;
    }
    inline void dfs(long long now,long long fa) {
        dep[now] =  dep[fa]+1;
        for (long long j = 1;j <= 50;j++) d[now][j] = quickpow(dep[now],j)+d[fa][j];
        for (long long i = 0;i < edges[now].size();i++)
            if (edges[now][i]  != fa) {
                dfs(edges[now][i],now);
                father[edges[now][i]][0] = now;
            }
    }
    inline void init() {
        for (long long j = 1;(1<<j) <= n;j++)
            for (long long i = 1;i <= n;i++)
                father[i][j] = father[father[i][j-1]][j-1];
    }
    inline long long lca(long long a,long long b) {
        if (dep[a] < dep[b]) swap(a,b);
        for (long long i = 20;i >= 0;i--)
            if (dep[father[a][i]] >= dep[b]) a = father[a][i];
        if (a == b) return a;
        for (long long i = 20;i >= 0;i--)
            if (father[a][i] != father[b][i]) {
                a = father[a][i];
                b = father[b][i];
            }
        return father[a][0];
    }
    int main() {
        scanf("%lld",&n);
        for (long long i = 1,u,v;i < n;i++) {
            scanf("%lld%lld",&u,&v);
            edges[u].push_back(v);
            edges[v].push_back(u);
        }
        dep[1] = -1;
        father[1][0] = 1;
        dfs(1,1);
        init();
        scanf("%lld",&m);
        while (m--) {
            long long a,b,k,LCA;
            scanf("%lld%lld%lld",&a,&b,&k);
            LCA = lca(a,b);
            printf("%lld
    ",((d[a][k]+d[b][k])-(d[LCA][k]+d[father[LCA][0]][k]))%MOD);
        }
        return 0;
    }
  • 相关阅读:
    Redis QPS测试
    go语言下载及安装
    企业级Docker镜像仓库Harbor部署与使用
    Linux格式化数据盘
    【一周一Q】如何快速复制有规律内容
    聊一聊职业能力之执行力
    面试那些事
    使用gitlab时候 fork仓库不会实时从主仓库更新解决方案
    从给定字符串中提取姓名
    测试Websocket建立通信,使用protobuf格式交换数据
  • 原文地址:https://www.cnblogs.com/lrj124/p/9733484.html
Copyright © 2011-2022 走看看