洛谷 P4427 求和
阿新 • • 發佈:2019-02-28
clu fine 題目中的 代碼 har href 預處理 etc 數組
傳送門啦
思路:
開始不腫麽容易想到用倍增,但是想到需要求 $ Lca $ ,倍增這種常數小而且快的方法就很方便了。求 $ Lca $ 就是一個最普通的板子。那現在考慮怎麽求題目中的結果。
樹上差分可能聽起來很高大上,但是前綴和並不陌生,樹上差分就理解成樹上前綴和就好了:
$ sum[u] + sum[v] - sum[lca(u , v)] ; $
樹上差分之前要先預處理出 $ dis $ 數組, $ dis[i][j] $ 表示從 $ i $ 出發到根節點(本題中的1號節點)的 $ j $ 次方。
for(re long long j = 1 ; j <= 50 ; ++ j) dis[x][j] = dis[fa][j] + quick_power(dep[x] , j) ;
這就是預處理的代碼了, $ dep $ 表示深度 , $ quick - power $ 為快速冪。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #define re register using namespace std ; const long long maxn = 300005 ; const long long mod = 998244353 ; inline long long read () { long long f = 1 , x = 0 ; char ch = getchar () ; while(ch > '9' || ch < '0') {if(ch == '-') f = -1 ; ch = getchar () ;} while(ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0' ; ch = getchar () ;} return x * f ; } inline void print (long long x){ if(x < 0) {putchar('-') ; x = -x ;} if(x > 9) print(x / 10) ; putchar(x % 10 + '0') ; } long long n , x , y , m , a , b , c ; long long head[maxn] , tot ; long long ans ; struct Edge { long long from , to , next ; }edge[maxn << 1] ; inline void add (long long u , long long v) { edge[++tot].from = u ; edge[tot].to = v ; edge[tot].next = head[u] ; head[u] = tot ; } long long quick_power (long long a , long long b) { long long res = a , ans = 1 ; while(b) { if(b & 1) ans = ans * res % mod ; res = res * res % mod ; b >>= 1 ; } return ans % mod ; } long long dep[maxn] , f[maxn][21] , dis[maxn][51]; inline void dfs (long long x , long long fa) { dep[x] = dep[fa] + 1 ; f[x][0] = fa ; for(re long long j = 1 ; j <= 50 ; ++ j) dis[x][j] = dis[fa][j] + quick_power(dep[x] , j) ; for(re long long i = 1 ; (1 << i) <= dep[x] ; ++ i) { f[x][i] = f[f[x][i - 1]][i - 1] ; } for(re long long i = head[x] ; i ; i = edge[i].next) { long long v = edge[i].to ; if(v != fa) dfs(v , x) ; } } inline long long lca (long long a , long long b) { if(dep[a] < dep[b]) swap(a , b) ; for(re long long i = 20 ; i >= 0 ; -- i) { if((1 << i) <= (dep[a] - dep[b]) ) { a = f[a][i] ; } } if(a == b) return a ; for(re long long i = 20 ; i >= 0 ; -- i) { if((1 << i) <= dep[a] && (f[a][i] != f[b][i])) { a = f[a][i] ; b = f[b][i] ; } } return f[a][0] ; } int main () { n = read () ; for(re long long i = 1 ; i <= n - 1 ; ++ i) { x = read () ; y = read () ; add(x , y) ; add(y , x) ; } dep[1] = -1 ; dfs(1 , 1) ; m = read () ; for(re long long i = 1 ; i <= m ; ++ i) { a = read () ; b = read () ; c = read () ; long long root = lca(a , b) ; ans = (dis[a][c] - dis[root][c] + dis[b][c] - dis[f[root][0]][c]) % mod ; //printf("%d %d %d %d\n" , dis[a][c] , dis[b][c] , dis[root][c] , quick_power(dep[root] , c) % mod ) ; print(ans) ; printf("\n") ; } return 0 ; }
洛谷 P4427 求和