# HackerRank Easy Addition problem solution

In this HackerRank Easy Addition problem solution, you are given a tree with N nodes and each node has a value associated with it. you are given Q queries, each of which is either an update or a retrieval operation. initially, all node values are zero.

we need to return the sum of the node values lying under the path from i to j and then modulo with 1000000007 value.

## Problem solution in Java Programming.

```import java.io.*;
import java.util.*;

public class Solution {

static int[] nxt;
static int[] succ;
static int[] ptr;
static int index = 1;

static void addEdge(int u, int v) {
nxt[index] = ptr[u];
ptr[u] = index;
succ[index++] = v;
}

static int lowestOneBit(int v) {
return v & (~v+1);
}

static int highestOneBitMask(int v) {
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
return v >> 1;
}

static class SchieberVishkinLCA {
int[] indices;
int[] maxHIndices;
int[] ancestorHeights;
int[] pathParents;

void build(int n) {
ancestorHeights = new int[n];
int[] parents = new int[n];
maxHIndices = new int[n];
Deque<Integer> vertices = new LinkedList<>();
indices = new int[n];

int currentIndex = 1;
while(!vertices.isEmpty()) {
int v = vertices.removeLast();
indices[v] = currentIndex++;
for(int it = ptr[v]; it > 0; it = nxt[it]) {
int u = succ[it];
parents[u] = v;
}
}

int head = 0;
int tail = 1;
int[] vertices2 = new int[n];
while(head != tail) {
int v = vertices2[head++];
for(int it = ptr[v]; it > 0; it = nxt[it]) {
int u = succ[it];
vertices2[tail++] = u;
}
}

for (int i = 0; i < tail; i++) {
int it = vertices2[i];
maxHIndices[it] = indices[it];
}
for (int i = tail-1; i >= 0; i--) {
int it = vertices2[i];
int v = it;
int parent = parents[v];
if(lowestOneBit(maxHIndices[parent]) < lowestOneBit(maxHIndices[v])) {
maxHIndices[parent] = maxHIndices[v];
}
}

ancestorHeights[0] = 0;
for (int i = 0; i < tail; i++) {
int it = vertices2[i];
int v = it;
ancestorHeights[v] = ancestorHeights[parents[v]] | lowestOneBit(maxHIndices[v]);
}

int[] temp = parents;
parents = pathParents;
pathParents = temp;

pathParents[indices[0]-1] = 0;
for (int i = 0; i < tail; i++) {
int it = vertices2[i];
int v = it;
for(int jt = ptr[v]; jt > 0; jt = nxt[jt]) {
int u = succ[jt];
if(maxHIndices[v] != maxHIndices[u]) {
pathParents[indices[u]-1] = v;
} else {
pathParents[indices[u]-1] = pathParents[indices[v]-1];
}
}
}
}

int query(int v, int u) {
int Iv = maxHIndices[v];
int Iu = maxHIndices[u];
int hIv = lowestOneBit(Iv);
int hIu = lowestOneBit(Iu);
int hbMask = highestOneBitMask((Iv ^ Iu) | hIv | hIu);
int j = lowestOneBit(ancestorHeights[v] & ancestorHeights[u] & ~hbMask);

int x, y;
if(j == hIv) {
x = v;
} else {
x = pathParents[(indices[v] & ~kMask | (kMask+1))-1];
}
if(j == hIu) {
y = u;
} else {
y = pathParents[(indices[u] & ~kMask | (kMask+1))-1];
}
return indices[x] < indices[y] ? x : y;
}
}

static int[] tParent;
static List<Integer> tOrd = new ArrayList<>();

static void treeGetorder(List<Integer>[] g, int root) {
int n = g.length;
tParent = new int[n];
Arrays.fill(tParent, -1);
tOrd.clear();

Deque<Integer> stk = new LinkedList<>();
while(!stk.isEmpty()) {
int i = stk.remove();
for(int j = g[i].size()-1; j >= 0; j--) {
int c = g[i].get(j);
if(tParent[c] == -1 && c != root) {
} else {
tParent[i] = c;
}
}
}
}

static final long MOD = 1000000007;

static long sum(long a, long b) {
return (a + b) % MOD;
}

static long mult(long a, long b) {
return (a * b) % MOD;
}

static long mult(long a, long b, long c) {
return (a * ((b*c) % MOD)) % MOD;
}

static long mult(long a, long b, long c, long d) {
return mult(mult(a, b), mult(c, d));
}

static void querysub(int[] adds, int a, int b, long x) {
if (x < 0) {
x += MOD;
}
}

static long inverse(int x) {
long a = x;
long b = MOD;
long u = 1;
long v = 0;
while(b > 0) {
long t = a / b;
a -= t * b;

long temp = a;
a = b;
b = temp;

u = sum(u, MOD - mult(t, v));

temp = u;
u = v;
v = temp;
}
return u;
}

static int[] getPowRs(int n, int r) {
int[] powRs = new int[n*2+1];
powRs[n] = 1;
for(int i = 1; i <= n; i++) {
powRs[n+i] = (int) mult(powRs[n+i-1], r);
}
long invR = inverse(r);
for(int i = 1; i <= n; i++) {
powRs[n-i] = (int) mult(powRs[n-i+1], invR);
}
return powRs;
}

static int[][] getCoefs(int n, int r, int[] powRs, int[] depth) {
int[][] coefs = new int[T][n+1];
for(int i = 0; i < n; i++) {
int d = depth[i];
coefs[0][i] = powRs[n-d];
coefs[1][i] = powRs[n+d];
coefs[2][i] = (int) mult(powRs[n-d], MOD-d);
coefs[3][i] = (int) mult(powRs[n+d], +d);
coefs[4][i] = (int) mult(powRs[n-d], MOD-d, MOD-d);
coefs[5][i] = (int) mult(powRs[n+d], +d, +d);
}
return coefs;
}

static final int T = 6;

static void print(int[] arr, int n, String s) {
System.out.print(s + ": ");
for (int i = 0; i < n; i++) {
System.out.print(arr[i] + " ");
}
System.out.print("\n");
}

@SuppressWarnings("unchecked")
public static void main(String[] args) throws IOException {

BufferedWriter bw = new BufferedWriter(new FileWriter(System.getenv("OUTPUT_PATH")));

StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int r = Integer.parseInt(st.nextToken());

List<Integer>[] g = new List[n];
for (int i = 0; i < n; i++) {
g[i] = new ArrayList<>();
}

for (int i = 0; i < n - 1; i++) {
st = new StringTokenizer(br.readLine());
int x = Integer.parseInt(st.nextToken())-1;
int y = Integer.parseInt(st.nextToken())-1;

}
treeGetorder(g, 0);
int[] depth = new int[n];
for (int j = 1; j < n; j++) {
int i = tOrd.get(j);
depth[i] = depth[tParent[i]] + 1;
}

nxt = new int[n];
succ = new int[n];
ptr = new int[n];
for (int i = 1; i < n; i++) {
}

SchieberVishkinLCA lca = new SchieberVishkinLCA();
lca.build(n);

int[] powRs = getPowRs(n, r);
int[][] adds = new int[T][n+1];

st = new StringTokenizer(br.readLine());
int u = Integer.parseInt(st.nextToken());
int q = Integer.parseInt(st.nextToken());

for (int i = 0; i < u; i++) {
st = new StringTokenizer(br.readLine());
int a1 = Integer.parseInt(st.nextToken());
int d1 = Integer.parseInt(st.nextToken());
int a2 = Integer.parseInt(st.nextToken());
int d2 = Integer.parseInt(st.nextToken());
int a = Integer.parseInt(st.nextToken())-1;
int b = Integer.parseInt(st.nextToken())-1;

int c = lca.query(a, b);
int cp = c == 0 ? n : tParent[c];

int dA = depth[a], dB = depth[b], dC = depth[c];
int p0 = powRs[n+dA];
int uB = dA + dB - dC * 2;
int q0 = powRs[n-dB+uB];
int t = (int) mult(a1, a2);
querysub(adds[0], a, cp, mult(t, p0));
querysub(adds[1], b, c,  mult(t, q0));

t = (int) sum(mult(a1, d2), mult(d1, a2));
int e = -dB+uB;
querysub(adds[2], a, cp, mult(t, p0));
querysub(adds[0], a, cp, mult(t, p0, dA));
querysub(adds[3], b, c,  mult(t, q0));
querysub(adds[1], b, c,  mult(t, q0, e));

t = (int) mult(d1, d2);
querysub(adds[4], a, cp, mult(t, p0));
querysub(adds[2], a, cp, mult(t, p0, dA, 2));
querysub(adds[0], a, cp, mult(t, p0, dA, dA));
querysub(adds[5], b, c,  mult(t, q0));
querysub(adds[3], b, c,  mult(t, q0, e, 2));
querysub(adds[1], b, c,  mult(t, q0, e, e));
}
int coefs[][] = getCoefs(n, r, powRs, depth);
int[] values = new int[n];
for(int t = 0; t < T; t++) {
for(int ix = n-1; ix > 0; -- ix) {
int i = tOrd.get(ix);
}
for (int i = 0; i < n; i++) {
}
for (int i = 0; i < n; i++) {
values[i] = (int) sum(values[i], adds[t][i]);
}
}
int[] sums = values.clone();
for(int ix = 1; ix < n; ix++) {
int i = tOrd.get(ix);
sums[i] = (int) sum(sums[i], sums[tParent[i]]);
}

for (int ii = 0; ii < q; ii++) {
st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken())-1;
int b = Integer.parseInt(st.nextToken())-1;

int c = lca.query(a, b);
long result = 0;
result = sum(result, sums[a]);
result = sum(result, sums[b]);
result = sum(result, MOD-values[c]);
if(c != 0) {
result = sum(result, MOD - mult(sums[tParent[c]], 2));
}
bw.write(result + "\n");
}

bw.newLine();
bw.close();
br.close();
}
}```

## Problem solution in C++ programming.

```#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
#include <set>
#include <map>
#include <queue>
#include <iostream>
#include <sstream>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <cctype>
#include <cassert>
#include <limits>
#include <functional>
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define rer(i,l,u) for(int (i)=(int)(l);(i)<=(int)(u);++(i))
#define reu(i,l,u) for(int (i)=(int)(l);(i)<(int)(u);++(i))
#if defined(_MSC_VER) || __cplusplus > 199711L
#define aut(r,v) auto r = (v)
#else
#define aut(r,v) __typeof(v) r = (v)
#endif
#define each(it,o) for(aut(it, (o).begin()); it != (o).end(); ++ it)
#define all(o) (o).begin(), (o).end()
#define pb(x) push_back(x)
#define mp(x,y) make_pair((x),(y))
#define mset(m,v) memset(m,v,sizeof(m))
#define INF 0x3f3f3f3f
#define INFL 0x3f3f3f3f3f3f3f3fLL
using namespace std;
typedef vector<int> vi; typedef pair<int,int> pii; typedef vector<pair<int,int> > vpii; typedef long long ll;
template<typename T, typename U> inline void amin(T &x, U y) { if(y < x) x = y; }
template<typename T, typename U> inline void amax(T &x, U y) { if(x < y) x = y; }

template<int MOD>
struct ModInt {
static const int Mod = MOD;
unsigned x;
ModInt(): x(0) { }
ModInt(signed sig) { int sigt = sig % MOD; if(sigt < 0) sigt += MOD; x = sigt; }
ModInt(signed long long sig) { int sigt = sig % MOD; if(sigt < 0) sigt += MOD; x = sigt; }
int get() const { return (int)x; }

ModInt &operator+=(ModInt that) { if((x += that.x) >= MOD) x -= MOD; return *this; }
ModInt &operator-=(ModInt that) { if((x += MOD - that.x) >= MOD) x -= MOD; return *this; }
ModInt &operator*=(ModInt that) { x = (unsigned long long)x * that.x % MOD; return *this; }
ModInt &operator/=(ModInt that) { return *this *= that.inverse(); }

ModInt operator+(ModInt that) const { return ModInt(*this) += that; }
ModInt operator-(ModInt that) const { return ModInt(*this) -= that; }
ModInt operator*(ModInt that) const { return ModInt(*this) *= that; }
ModInt operator/(ModInt that) const { return ModInt(*this) /= that; }

ModInt inverse() const {
long long a = x, b = MOD, u = 1, v = 0;
while(b) {
long long t = a / b;
a -= t * b; std::swap(a, b);
u -= t * v; std::swap(u, v);
}
return ModInt(u);
}
ModInt operator-() const { ModInt t; t.x = x == 0 ? 0 : Mod - x; return t; }
};
typedef ModInt<1000000007> mint;

struct To {
typedef int Vertex;
Vertex to;
To() { }
To(Vertex to_): to(to_) { }
};
template<typename To_>
struct StaticGraph {
typedef To_ To;
typedef typename To::Vertex Vertex;
typedef std::pair<Vertex,To> Edge;
typedef const To *const_iterator;

void init(int n_, const std::vector<Edge> &edges) {
n = n_; int m = edges.size();
tos.resize(m+1); offsets.resize(n+1);
for(int e = 0; e < m; e ++) offsets[edges[e].first] ++;
for(int v = 1; v <= n_; v ++) offsets[v] += offsets[v-1];
for(int e = 0; e < m; e ++)
tos[-- offsets[edges[e].first]] = edges[e].second;
}
int numVertices() const { return n; }
int numEdges() const { return tos.size() - 1; }

inline const_iterator edgesBegin(int v) const { return &tos[offsets[v]]; }
inline const_iterator edgesEnd(int v) const { return &tos[offsets[v+1]]; }
private:
int n;
std::vector<To> tos;
std::vector<int> offsets;
};

class SchieberVishkinLCA {
public:
typedef StaticGraph<To> Graph;
typedef unsigned Word;
typedef Graph::Vertex Vertex;
private:

static inline Word lowestOneBit(Word v) {
return v & (~v+1);
}
static inline Word highestOneBitMask(Word v) {
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
return v >> 1;
}

std::vector<Word> indices;            //Vertex -> index
std::vector<Word> maxHIndices;        //Vertex -> index
std::vector<Word> ancestorHeights;    //Vertex -> Word
std::vector<Vertex> pathParents;    //index-1 -> Vertex
public:
//g
void build(const Graph &g, Vertex root) {
return build(g, std::vector<Vertex>(1, root));
}
void build(const Graph &g, const std::vector<Vertex> &roots) {
int N = g.numVertices();

ancestorHeights.resize(N);
std::vector<Vertex> parents(N);
maxHIndices.resize(N);
std::vector<Vertex> vertices; vertices.reserve(N);
indices.resize(N);

//inorder traversal
Word currentIndex = 1;
for(int ri = 0; ri < (int)roots.size(); ri ++) {
Vertex root = roots[ri];
parents[root] = root;    //
vertices.push_back(root);
}
while(!vertices.empty()) {
Vertex v = vertices.back(); vertices.pop_back();
indices[v] = currentIndex ++;
for(const Graph::To *it = g.edgesBegin(v); it != g.edgesEnd(v); ++ it) {
parents[it->to] = v;
vertices.push_back(it->to);
}
}

//BFS ()
int head = 0, tail = roots.size();
vertices.resize(N);
for(int ri = 0; ri < (int)roots.size(); ri ++)
vertices[ri] = roots[ri];
while(head != tail) {
Vertex v = vertices[head ++];
for(const Graph::To *it = g.edgesBegin(v); it != g.edgesEnd(v); ++ it)
vertices[tail ++] = it->to;
}

//
for(std::vector<Vertex>::const_iterator it = vertices.begin(); it != vertices.end(); ++ it)
maxHIndices[*it] = indices[*it];
for(std::vector<Vertex>::const_reverse_iterator it = vertices.rbegin(); it != vertices.rend(); ++ it) {
Vertex v = *it, parent = parents[v];
if(lowestOneBit(maxHIndices[parent]) < lowestOneBit(maxHIndices[v]))
maxHIndices[parent] = maxHIndices[v];
}

//A
for(int ri = 0; ri < (int)roots.size(); ri ++) {
Vertex root = roots[ri];
ancestorHeights[root] = 0;
}
for(std::vector<Vertex>::const_iterator it = vertices.begin(); it != vertices.end(); ++ it) {
Vertex v = *it;
ancestorHeights[v] = ancestorHeights[parents[v]] | lowestOneBit(maxHIndices[v]);
}

pathParents.swap(parents);    //
for(int ri = 0; ri < (int)roots.size(); ri ++) {
Vertex root = roots[ri];
pathParents[indices[root]-1] = root;
}
for(std::vector<Vertex>::const_iterator it = vertices.begin(); it != vertices.end(); ++ it) {
Vertex v = *it;
for(const Graph::To *jt = g.edgesBegin(v); jt != g.edgesEnd(v); ++ jt) {
if(maxHIndices[v] != maxHIndices[jt->to])
pathParents[indices[jt->to]-1] = v;
else
pathParents[indices[jt->to]-1] = pathParents[indices[v]-1];
}
}
}

Vertex query(Vertex v, Vertex u) const {
//binary treeLCA
Word Iv = maxHIndices[v], Iu = maxHIndices[u];
Word hIv = lowestOneBit(Iv), hIu = lowestOneBit(Iu);
Word hbMask = highestOneBitMask((Iv ^ Iu) | hIv | hIu);
Word j = lowestOneBit(ancestorHeights[v] & ancestorHeights[u] & ~hbMask);
//j = hI(lca(v,u))  (hI(x) = 2^(complete binary treeI(x)), I(x) = maxHIndices[x])
//(hI(lca(v,u)) = j)hI(v)hI(u)
Vertex x, y;
if(j == hIv) x = v;
else {            //lcav
Word kMask = highestOneBitMask(ancestorHeights[v] & (j-1));    //vj
x = pathParents[(indices[v] & ~kMask | (kMask+1))-1];    //indices[v]k
}
if(j == hIu) y = u;
else {            //lcau
Word kMask = highestOneBitMask(ancestorHeights[u] & (j-1));    //uj
y = pathParents[(indices[u] & ~kMask | (kMask+1))-1];    //indices[u]k
}
return indices[x] < indices[y] ? x : y;    //in-order
}
};
vector<int> t_parent;
vi t_ord;

void tree_getorder(const vector<vi> &g, int root) {
int n = g.size();
t_parent.assign(n, -1);
t_ord.clear();

vector<int> stk; stk.push_back(root);
while(!stk.empty()) {
int i = stk.back(); stk.pop_back();
t_ord.push_back(i);
for(int j = (int)g[i].size()-1; j >= 0; j --) {
int c = g[i][j];
if(t_parent[c] == -1 && c != root)
stk.push_back(c);
else
t_parent[i] = c;
}
}
}

void querysub(vector<mint> &adds, int A, int B, mint x) {
}

int main() {
typedef StaticGraph<To> Graph;
int N, R;
scanf("%d%d", &N, &R);
vector<vi> g(N);
rep(i, N-1) {
int x, y;
scanf("%d%d", &x, &y), -- x, -- y;
g[x].push_back(y);
g[y].push_back(x);
}
tree_getorder(g, 0);
vector<int> depth(N, 0);
reu(ix, 1, N) {
int i = t_ord[ix];
depth[i] = depth[t_parent[i]] + 1;
}
vector<Graph::Edge> edges;
reu(i, 1, N)
edges.push_back(Graph::Edge(t_parent[i], i));
Graph gg; gg.init(N, edges);
SchieberVishkinLCA lca; lca.build(gg, 0);
vector<mint> powRs(N*2+1);
powRs[N] = 1;
rer(i, 1, N) powRs[N+i] = powRs[N+i-1] * R;
mint invR = mint(R).inverse();
rer(i, 1, N) powRs[N-i] = powRs[N-i+1] * invR;
const int T = 6;
rep(t, T) coefs[t].assign(N+1, mint());
rep(i, N) {
int d = depth[i];
coefs[0][i] = powRs[N-d];
coefs[1][i] = powRs[N+d];
coefs[2][i] = powRs[N-d] * -d;
coefs[3][i] = powRs[N+d] * +d;
coefs[4][i] = powRs[N-d] * -d * -d;
coefs[5][i] = powRs[N+d] * +d * +d;
}
rep(t, T) adds[t].assign(N+1, mint());
vector<mint> values(N, mint());
int U, Q;
scanf("%d%d", &U, &Q);
rep(ii, U) {
int a1, d1, a2, d2, A, B;
scanf("%d%d%d%d%d%d", &a1, &d1, &a2, &d2, &A, &B), -- A, -- B;
//(a1 + z d1) (a2 + z d2) R^z
//= a1 a2 R^z + (a1 d2 + d1 a2) z R^z + d1 d2 z^2 R^z
int C = lca.query(A, B), Cp = C == 0 ? N : t_parent[C];
int dA = depth[A], dB = depth[B], dC = depth[C];
int uC = dA - dC, uB = dA + dB - dC * 2;
mint p = powRs[N+dA], q = powRs[N-dB+uB];
int e = -dB+uB;
//a1 a2 R^z
if(1) {
mint t = mint(a1) * a2;
querysub(adds[0], A, Cp, t * p);
querysub(adds[1], B, C,  t * q);
}
//(a1 d2 + d1 a2) z R^z
if(1) {
mint t = mint(a1) * d2 + mint(d1) * a2;
querysub(adds[2], A, Cp, t * p);
querysub(adds[0], A, Cp, t * p * dA);
querysub(adds[3], B, C,  t * q);
querysub(adds[1], B, C,  t * q * e);
}
//d1 d2 z^2 R^z
if(1) {
mint t = mint(d1) * d2;
querysub(adds[4], A, Cp, t * p);
querysub(adds[2], A, Cp, t * p * dA * 2);
querysub(adds[0], A, Cp, t * p * dA * dA);
querysub(adds[5], B, C,  t * q);
querysub(adds[3], B, C,  t * q * e * 2);
querysub(adds[1], B, C,  t * q * e * e);
}
}
rep(t, T) {
for(int ix = N-1; ix > 0; -- ix) {
int i = t_ord[ix];
}
rep(i, N)
//        cerr << t << ": "; rep(i, N) cerr << adds[t][i].get() << ", "; cerr << endl;
rep(i, N)
}
//    cerr << "values: "; rep(i, N) cerr << values[i].get() << ", "; cerr << endl;
//    }
vector<mint> sums = values;
for(int ix = 1; ix < N; ++ ix) {
int i = t_ord[ix];
sums[i] += sums[t_parent[i]];
}
rep(ii, Q) {
int A, B;
scanf("%d%d", &A, &B), -- A, -- B;
int C = lca.query(A, B);
mint ans = 0;
ans += sums[A];
ans += sums[B];
ans -= values[C];
if(C != 0)
ans -= sums[t_parent[C]] * 2;
printf("%d\n", ans.get());
}
return 0;
}```

## Problem solution in C programming.

```#include<stdio.h>
#include<stdlib.h>
#define MOD 1000000007
typedef struct _lnode
{
int x;
int w;
struct _lnode *next;
}lnode;
typedef struct _data
{
long long term10_fa;
long long term20_fa;
long long term21_fa;
long long term30_fa;
long long term31_fa;
long long term32_fa;
long long term10_ia;
long long term20_ia;
long long term21_ia;
long long term30_ia;
long long term31_ia;
long long term32_ia;
long long term10_fs;
long long term20_fs;
long long term21_fs;
long long term30_fs;
long long term31_fs;
long long term32_fs;
long long term10_is;
long long term20_is;
long long term21_is;
long long term30_is;
long long term31_is;
long long term32_is;
}data;
int N, R, RI, DP[18][100000], level[100000];
long long s[100000], dis[100000], Rp[100005], IRp[100005];
lnode *table[100000] = {0};
data tree[100000] = {0};
void insert_edge(int x, int y, int w)
{
lnode *t = malloc(sizeof(lnode));
t -> x = y;
t -> w = w;
t -> next = table[x];
table[x] = t;
t = malloc(sizeof(lnode));
t -> x = x;
t -> w = w;
t -> next = table[y];
table[y] = t;
return;
}
void preprocess()
{
int i, j;
level[0] = 0;
DP[0][0] = 0;
dfs0(0);
for( i = 1 ; i < 18 ; i++ )
{
for( j = 0 ; j < N ; j++ )
{
DP[i][j] = DP[i-1][DP[i-1][j]];
}
}
return;
}
int lca(int a, int b)
{
int i;
if( level[a] > level[b] )
{
i = a;
a = b;
b = i;
}
int d = level[b] - level[a];
for( i = 0 ; i < 18 ; i++ )
{
if( d & ( 1 << i ) )
{
b = DP[i][b];
}
}
if( a == b )
{
return a;
}
for( i = 17 ; i >= 0 ; i-- )
{
if( DP[i][a] != DP[i][b] )
{
a = DP[i][a], b = DP[i][b];
}
}
return DP[0][a];
}
void dfs0(int u)
{
lnode *x;
for( x = table[u] ; x ; x = x -> next )
{
if( x -> x != DP[0][u] )
{
DP[0][x -> x] = u;
level[x -> x] = level[u] + 1;
dfs0(x -> x);
}
}
return;
}
void dfs1(int u)
{
lnode *x;
for( x = table[u] ; x ; x = x -> next )
{
if( x -> x != DP[0][u] )
{
dfs1(x -> x);
tree[u].term10_fa = ( tree[u].term10_fa + tree[x -> x].term10_fa * R ) % MOD;
tree[u].term10_ia = ( tree[u].term10_ia + tree[x -> x].term10_ia * RI ) % MOD;
tree[u].term10_fs = ( tree[u].term10_fs + tree[x -> x].term10_fs * R ) % MOD;
tree[u].term10_is = ( tree[u].term10_is + tree[x -> x].term10_is * RI ) % MOD;
tree[u].term20_fa = ( tree[u].term20_fa + tree[x -> x].term20_fa * R ) % MOD;
tree[u].term21_fa = ( tree[u].term21_fa + ( tree[x -> x].term21_fa + tree[x -> x].term20_fa ) * R ) % MOD;
tree[u].term20_ia = ( tree[u].term20_ia + tree[x -> x].term20_ia * RI ) % MOD;
tree[u].term21_ia = ( tree[u].term21_ia + ( tree[x -> x].term21_ia - tree[x -> x].term20_ia + MOD ) * RI ) % MOD;
tree[u].term20_fs = ( tree[u].term20_fs + tree[x -> x].term20_fs * R ) % MOD;
tree[u].term21_fs = ( tree[u].term21_fs + ( tree[x -> x].term21_fs + tree[x -> x].term20_fs ) * R ) % MOD;
tree[u].term20_is = ( tree[u].term20_is + tree[x -> x].term20_is * RI ) % MOD;
tree[u].term21_is = ( tree[u].term21_is + ( tree[x -> x].term21_is - tree[x -> x].term20_is + MOD ) * RI ) % MOD;
tree[u].term30_fa = ( tree[u].term30_fa + tree[x -> x].term30_fa * R ) % MOD;
tree[u].term31_fa = ( tree[u].term31_fa + ( tree[x -> x].term31_fa + tree[x -> x].term30_fa ) * R ) % MOD;
tree[u].term32_fa = ( tree[u].term32_fa + ( tree[x -> x].term32_fa + 2 * tree[x -> x].term31_fa + tree[x -> x].term30_fa ) * R ) % MOD;
tree[u].term30_ia = ( tree[u].term30_ia + tree[x -> x].term30_ia * RI ) % MOD;
tree[u].term31_ia = ( tree[u].term31_ia + ( tree[x -> x].term31_ia - tree[x -> x].term30_ia + MOD ) * RI ) % MOD;
tree[u].term32_ia = ( tree[u].term32_ia + ( tree[x -> x].term32_ia - 2 * tree[x -> x].term31_ia + tree[x -> x].term30_ia + 2 * MOD ) * RI ) % MOD;
tree[u].term30_fs = ( tree[u].term30_fs + tree[x -> x].term30_fs * R ) % MOD;
tree[u].term31_fs = ( tree[u].term31_fs + ( tree[x -> x].term31_fs + tree[x -> x].term30_fs ) * R ) % MOD;
tree[u].term32_fs = ( tree[u].term32_fs + ( tree[x -> x].term32_fs + 2 * tree[x -> x].term31_fs + tree[x -> x].term30_fs ) * R ) % MOD;
tree[u].term30_is = ( tree[u].term30_is + tree[x -> x].term30_is * RI ) % MOD;
tree[u].term31_is = ( tree[u].term31_is + ( tree[x -> x].term31_is - tree[x -> x].term30_is + MOD ) * RI ) % MOD;
tree[u].term32_is = ( tree[u].term32_is + ( tree[x -> x].term32_is - 2 * tree[x -> x].term31_is + tree[x -> x].term30_is + 2 * MOD ) * RI ) % MOD;
}
}
s[u] = ( tree[u].term10_fa + tree[u].term10_ia - tree[u].term10_fs - tree[u].term10_is + 2 * MOD ) % MOD;
s[u] = ( s[u] + tree[u].term21_fa + tree[u].term21_ia - tree[u].term21_fs - tree[u].term21_is + 2 * MOD ) % MOD;
s[u] = ( s[u] + tree[u].term32_fa + tree[u].term32_ia - tree[u].term32_fs - tree[u].term32_is + 2 * MOD ) % MOD;
return;
}
void dfs2(int u)
{
lnode *x;
if( u != DP[0][u] )
{
dis[u] = ( s[u] + dis[DP[0][u]] ) % MOD;
}
else
{
dis[u] = s[u];
}
for( x = table[u] ; x ; x = x -> next )
{
if( x -> x != DP[0][u] )
{
dfs2(x -> x);
}
}
return;
}
long long modInverse(long long a, long long mod)
{
long long b0 = mod, t, q;
long long x0 = 0, x1 = 1;
while( a > 1 )
{
q = a / mod;
t = mod;
mod = a % mod;
a = t;
t = x0;
x0 = x1 - q * x0;
x1 = t;
}
if( x1 < 0 )
{
x1 += b0;
}
return x1;
}
int main()
{
int U, Q, x, y, a1, a2, d1, d2, t1, t2, i;
long long ans;
scanf("%d%d", &N, &R);
for( i = 0 ; i < N - 1 ; i++ )
{
scanf("%d%d", &x, &y);
insert_edge(x-1, y-1, 1);
}
preprocess();
RI = modInverse(R, MOD);
Rp[0] = IRp[0] = 1;
for( i = 1 ; i < 100005 ; i++ )
{
Rp[i] = Rp[i-1] * R % MOD;
IRp[i] = IRp[i-1] * RI % MOD;
}
scanf("%d%d", &U, &Q);
while(U--)
{
scanf("%d%d%d%d%d%d", &a1, &d1, &a2, &d2, &x, &y);
i = lca(x-1, y-1);
t1 = level[x-1] - level[i];
t2 = level[y-1] - level[i];
tree[x-1].term10_fa = ( tree[x-1].term10_fa + a1 * (long long)a2 ) % MOD;
tree[x-1].term20_fa = ( tree[x-1].term20_fa + a1 * (long long)d2 + a2 * (long long)d1 ) % MOD;
tree[x-1].term30_fa = ( tree[x-1].term30_fa + d1 * (long long)d2 ) % MOD;
tree[i].term10_fs = ( tree[i].term10_fs + a1 * (long long)a2 % MOD * Rp[t1] ) % MOD;
tree[i].term20_fs = ( tree[i].term20_fs + ( a1 * (long long)d2 + a2 * (long long)d1 ) % MOD * Rp[t1] ) % MOD;
tree[i].term21_fs = ( tree[i].term21_fs + ( a1 * (long long)d2 + a2 * (long long)d1 ) % MOD * t1 % MOD * Rp[t1] ) % MOD;
tree[i].term30_fs = ( tree[i].term30_fs + d1 * (long long)d2 % MOD * Rp[t1] ) % MOD;
tree[i].term31_fs = ( tree[i].term31_fs + d1 * (long long)d2 % MOD * t1 % MOD * Rp[t1] ) % MOD;
tree[i].term32_fs = ( tree[i].term32_fs + d1 * (long long)d2 % MOD * t1 % MOD * t1 % MOD * Rp[t1] ) % MOD;
tree[y-1].term10_ia = ( tree[y-1].term10_ia + a1 * (long long)a2 % MOD * Rp[t1+t2] ) % MOD;
tree[y-1].term20_ia = ( tree[y-1].term20_ia + ( a1 * (long long)d2 + a2 * (long long)d1 ) % MOD * Rp[t1+t2] ) % MOD;
tree[y-1].term21_ia = ( tree[y-1].term21_ia + ( a1 * (long long)d2 + a2 * (long long)d1 ) % MOD * ( t1 + t2 ) % MOD * Rp[t1+t2] ) % MOD;
tree[y-1].term30_ia = ( tree[y-1].term30_ia + d1 * (long long)d2 % MOD * Rp[t1+t2] ) % MOD;
tree[y-1].term31_ia = ( tree[y-1].term31_ia + d1 * (long long)d2 % MOD * ( t1 + t2 ) % MOD * Rp[t1+t2] ) % MOD;
tree[y-1].term32_ia = ( tree[y-1].term32_ia + d1 * (long long)d2 % MOD * ( t1 + t2 ) % MOD * ( t1 + t2 ) % MOD * Rp[t1+t2] ) % MOD;
if(i)
{
tree[DP[0][i]].term10_is = ( tree[DP[0][i]].term10_is + a1 * (long long)a2 % MOD * Rp[t1+t2] % MOD * IRp[t2+1] ) % MOD;
tree[DP[0][i]].term20_is = ( tree[DP[0][i]].term20_is + ( a1 * (long long)d2 + a2 * (long long)d1 ) % MOD * Rp[t1+t2] % MOD * IRp[t2+1] ) % MOD;
tree[DP[0][i]].term21_is = ( tree[DP[0][i]].term21_is + ( a1 * (long long)d2 + a2 * (long long)d1 ) % MOD * ( t1 - 1 + MOD ) % MOD * Rp[t1+t2] % MOD * IRp[t2+1] ) % MOD;
tree[DP[0][i]].term30_is = ( tree[DP[0][i]].term30_is + d1 * (long long)d2 % MOD * Rp[t1+t2] % MOD * IRp[t2+1] ) % MOD;
tree[DP[0][i]].term31_is = ( tree[DP[0][i]].term31_is + d1 * (long long)d2 % MOD * ( t1 - 1 + MOD ) % MOD * Rp[t1+t2] % MOD * IRp[t2+1] ) % MOD;
tree[DP[0][i]].term32_is = ( tree[DP[0][i]].term32_is + d1 * (long long)d2 % MOD * ( t1 - 1 + MOD ) % MOD * ( t1 - 1 + MOD ) % MOD * Rp[t1+t2] % MOD * IRp[t2+1] ) % MOD;
}
}
dfs1(0);
dfs2(0);
while(Q--)
{
scanf("%d%d", &x, &y);
a1 = lca(x-1, y-1);
ans = ( dis[x-1] + dis[y-1] - dis[a1] + MOD ) % MOD;
if(a1)
{
ans = ( ans - dis[DP[0][a1]] + MOD ) % MOD;
}
printf("%lld\n", ans);
}
return 0;
}```