Description

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

Input

第一行包含一个正整数n ,表示树的节点数。
之后n-1 行每行两个空格隔开的正整数i,j ,表示树上的一条连接点i 和点j 的边。
之后一行一个正整数m ,表示询问的数量。
之后每行三个空格隔开的正整数i,j,k ,表示询问从点i 到点j 的路径上所有节点深度的k 次方和。
由于这个结果可能非常大,输出其对998244353 取模的结果。
树的节点从1 开始标号,其中1 号节点为树的根。
 

Output

对于每组数据输出一行一个正整数表示取模后的结果。
1≤n,m≤300000,1≤k≤50
 

Sample Input

5
1 2
1 3
2 4
2 5
2
1 4 5
5 4 45

Sample Output

33
503245989
说明
样例解释
以下用d(i) 表示第i 个节点的深度。
对于样例中的树,有d(1)=0,d(2)=1,d(3)=1,d(4)=2,d(5)=2。
因此第一个询问答案为(2^5 + 1^5 + 0^5) mod 998244353 = 33 
第二个询问答案为(2^45 + 1^45 + 2^45) mod 998244353 = 503245989。

Solution

因为这个k很小,所以就是个树上差分板子

预处理出深度之后弄个树上前缀和(对于不同的k暴力存就好,因为k最大50)

预处理复杂度是$O(nk)$的

然后每次询问的答案其实就是两个点的前缀和减掉他们的$LCA$的前缀和再加上他们的$LCA$的k次方

#include <bits/stdc++.h>

using namespace std ;

#define N 300010
#define mod 998244353
#define inf 0x3f3f3f3f
#define ll long long int n , m ;
int dep[ N ] , siz[ N ] , top[ N ] , fa[ N ] ;
int head[ N ] , cnt ;
ll c[ N ][ ] ;
struct node {
int to , nxt ;
} e[ N << ] ; void ins( int u , int v ) {
e[ ++ cnt ].to = v ;
e[ cnt ].nxt = head[ u ] ;
head[ u ] = cnt ;
} void dfs1( int u ) {
siz[ u ] = ;
for( int i = head[ u ] ; i ; i = e[ i ].nxt ) {
int v = e[ i ].to ;
if( v == fa[ u ] ) continue ;
fa[ v ] = u ;
dep[ v ] = dep[ u ] + ;
dfs1( v ) ;
siz[ u ] += siz[ v ] ;
}
} void dfs2( int u , int topf ) {
top[ u ] = topf ;
int k = ;
for( int i = head[ u ] ; i ; i = e[ i ].nxt ) {
if( e[ i ].to != fa[ u ] && siz[ e[ i ].to ] > siz[ k ] )
k = e[ i ].to ;
}
if( !k ) return ;
dfs2( k , topf ) ;
for( int i = head[ u ] ; i ; i = e[ i ].nxt ) {
if( e[ i ].to != k && e[ i ].to != fa[ u ] )
dfs2( e[ i ].to , e[ i ].to ) ;
}
} void dfs3( int u ) {
ll x = ;
for( int k = ; k <= ; k ++ ) {
x = 1ll * x * dep[ u ] % mod ;
c[ u ][ k ] = ( 1ll * c[ fa[ u ] ][ k ] + x ) % mod ;
}
for( int i = head[ u ] ; i ; i = e[ i ].nxt ) {
if( e[ i ].to == fa[ u ] ) continue ;
dfs3( e[ i ].to ) ;
}
} int lca( int x , int y ) {
while( top[ x ] != top[ y ] ) {
if( dep[ top[ x ] ] < dep[ top[ y ] ] ) swap( x , y ) ;
x = fa[ top[ x ] ] ;
}
if( dep[ x ] > dep[ y ] ) swap( x , y ) ;
return x ;
} ll power( ll a , ll b ) {
ll ans = , base = a ;
while( b ) {
if( b& ) ans = ans * base % mod ;
base = base * base % mod ;
b >>= ;
}
return ans % mod ;
} int main() {
scanf( "%d" , &n ) ;
for(int i = , u , v ; i < n ; i ++ ) {
scanf( "%d%d" , &u , &v ) ;
ins( u , v ) ; ins( v , u ) ;
}
dfs1( ) ; dfs2( , ) ; dfs3( ) ;
scanf( "%d" , &m ) ;
while( m -- ) {
int u , v , k ;
scanf( "%d%d%d" , &u , &v , &k ) ;
int l = lca( u , v ) ;
printf( "%lld\n" , ( c[ u ][ k ] % mod + c[ v ][ k ] % mod - * c[ l ][ k ] % mod + power( dep[ l ] , k ) + mod ) % mod ) ;
}
return ;
}

BZOJ5293: [Bjoi2018]求和 树上差分的更多相关文章

  1. BZOJ5293:[BJOI2018]求和(LCA,差分)

    Description master 对树上的求和非常感兴趣.他生成了一棵有根树,并且希望多次询问这棵树上一段路径上所有节点深度的k  次方和,而且每次的k 可能是不同的.此处节点深度的定义是这个节点 ...

  2. bzoj5293: [Bjoi2018]求和

    题目链接 bzoj5293: [Bjoi2018]求和 题解 暴力 对于lca为1的好坑啊.... 代码 #include<cmath> #include<cstdio> #i ...

  3. [BZOJ5293][BJOI2018]求和(倍增)

    裸的树上倍增. #include<cstdio> #include<cstring> #include<algorithm> #define rep(i,l,r) ...

  4. Luogu4427 [BJOI2018]求和 (树上差分)

    预处理,树上差分.注意深度减一 #include <cstdio> #include <iostream> #include <cstring> #include ...

  5. 【BZOJ5293】[BJOI2018]求和(前缀和,LCA)

    [BZOJ5293][BJOI2018]求和(前缀和,LCA) 题面 BZOJ 洛谷 题解 送分题??? 预处理一下\(k\)次方的前缀和. 然后求个\(LCA\)就做完了?... #include& ...

  6. poj3417lca+树上差分

    /* 给定n个点的树,在其中加入m条新边(称为非树边) 现在可以割断一条树边,一条非树边,使图分裂成两个联通块,请问有几种切割方式 对树边进行分情况讨论 如果树边不处在环中,则割断这条树边后可以割断任 ...

  7. BZOJ4999 This Problem Is Too Simple!(树上差分+dfs序+树状数组)

    对每个权值分别考虑.则只有单点加路径求和的操作.树上差分转化为求到根的路径和,子树加即可.再差分后bit即可.注意树上差分中根的父亲是0,已经忘了是第几次因为这个挂了. #include<ios ...

  8. [luogu]P2680 运输计划[二分答案][树上差分]

    [luogu]P2680 [NOIP2015]运输计划 题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n ...

  9. 【题解】CF986E Prince's Problem(树上差分+数论性质)

    [题解]CF986E Prince's Problem(树上差分+数论性质) 题目大意: 给定你一棵树,有点权\(val_i\le 10^7\).现在有\(m\)组询问给定参数\(x,y,w\)问你对 ...

随机推荐

  1. 理解CopyOnWriteArrayList

    CopyOnWriteArrayList,顾名思义,Write的时候总是要Copy,也就是说对于任何可变的操作(add.set.remove)都是伴随复制这个动作的 A thread-safe var ...

  2. vue学习之四组件系统

    vue.js既然是框架,那就不能只是简单的完成数据模板引擎的任务,它还提供了页面布局的功能.本文详细介绍使用vue.js进行页面布局的强大工具,vue.js组件系统. 一.Vue.js组件系统 每一个 ...

  3. 解决svn log显示no author,no date的方法之一

    https://blog.csdn.net/feixiang_song/article/details/37809341 关于mac自带的svn的配置请参考该博客:点击打开链接 问题: 在linux执 ...

  4. [django]Django model中数据批量导入bulk_create()

    参考: https://www.cnblogs.com/ccorz/p/Django-model-zhong-shu-ju-pi-liang-dao-rubulkcreat.html import o ...

  5. [kx]为什么计算机能读懂 1 和 0 ?

    CPU如何实现运算的? 下面是一个小伙的总结, 从物理电路到逻辑运算到数字电路,一步一步的好理解. 最好能看看那本<编码 隐匿在计算机软硬件背后的语言>的书. 为什么计算机能读懂 1 和 ...

  6. EM算法小结

    一.什么是EM算法? EM算法是机器学习中一个很重要的算法,即期望最大化算法,主要包括以下两个步骤: E步骤:estimate the expected values M步骤:re-estimate ...

  7. [LeetCode] 560. Subarray Sum Equals K_Medium

    Given an array of integers and an integer k, you need to find the total number of continuous subarra ...

  8. android studio 3.0 安装配置

    1.  安装jdk1.8 2.复制android sdk  设置代理  mirrors.neusoft.edu.cn  端口 80 http代理  更新sdk  安装  android support ...

  9. http协议基础(九)响应首部字段

    响应首部字段: 服务器向客户端返回响应报文中所使用的字段,用于补充的附加信息.服务器信息.以及对客户端的附加要求等 1.Accept-Ranges 告知客户端服务器能否处理范围请求,以指定获取服务器的 ...

  10. 摘要JSR168 PORLET标准手册汉化整理

    本规范汉化资源搜集整理于网上并由我作了些修改和添加,主要为适应大陆的语辞.用语及其他未译之处. 由于本人于水平有限,如有错误,请各位高手指正:若有高见,希望不吝言辞,同为中国开源作项献. 特此严重感谢 ...