Dynamic Summation
Difficulty: Hard

Given a tree of _N_ nodes, where each node is uniquely numbered in between _[1, N]_. Each node also has a value which is initially 0. You need to perform following two operations in the tree.  

1. Update Operation
2. Report Operation

**Update Operation**

    U r t a b

Adds <code>a<sup>b</sup> + (a+1)<sup>b</sup> + (b+1)<sup>a</sup></code> to all nodes in the subtree rooted at `t`, considering that tree is rooted at `r` (see explanation for more details).  

**Report Operation**

    R r t m
    
Output the sum of all nodes in the subtree rooted at `t`, considering that tree is rooted at `r`. Output the sum modulo `m` (see explanation for more details).

**Input Format**

First line contains _N_, number of nodes in the tree.  
Next _N-1_ lines contain two space separated integers _x_ and _y_ which denote that there is an edge between node _x_ and node _y_.  
Next line contains _Q_, number of queries to follow.  
Next _Q_ lines follow, each line will be either a report operation or an update operation.  

**Output Format**

For each report query output the answer in a separate line.

**Constraints**

1 ≤ _N_ ≤ 100000  
1 ≤ _Q_ ≤ 100000  
1 ≤ _m_ ≤ 101  
1 ≤ _r, t, x, y_ ≤ _N_  
_x_ &ne; _y_  
1 ≤ _a, b_ ≤ 10<sup>18</sup>  

**Notes**

1. There will be at most one edge between a pair of nodes.
2. There will be no loop.
2. Tree will be completely connected. 

**Sample Input**

	4
	1 2
	2 3
	3 4
	4
	U 3 2 2 2
	U 2 3 2 2
	R 1 2 8
	R 4 3 9

**Sample Output**

	2
    3
   
**Explanation**

Initially Values in each node : [0,0,0,0]  
The first query is `U 3 2 2 2`. Here, tree is rooted at 3. It looks like 

        3(0)
       / \
      /   \
     2(0)  4(0)
     |
     |
     1(0)

For the sub tree rooted at 2 ( nodes 2 and 1 ), we add a<sup>b</sup>  + (a+1)<sup>b</sup> + (b+1)<sup>a</sup> = 2<sup>2</sup> + 3<sup>2</sup> + 3<sup>2</sup> = 22. After first update operation, nodes 1, 2, 3, and 4 will have values 22, 22, 0 and 0 respectively.  

        3(0)
       / \
      /   \
     2(22) 4(0)
     |
     |
     1(22)

The second query is `U 2 3 2 2`. Here, tree is rooted at 2. It looks like

        2(22)
       / \
      /   \
     1(22) 3(0)
           |
           |
           4(0)

For the sub tree rooted at 3 (nodes 3 and 4), we add a<sup>b</sup> + (a+1)<sup>b</sup> + (b+1)<sup>a</sup> = 2<sup>2</sup> + 3<sup>2</sup> + 3<sup>2</sup> = 22. After second update operation, nodes 1, 2, 3, and 4 each have values 22,22,22,22 respectively.  

        2(22)
       / \
      /   \
     1(22) 3(22)
           |
           |
           4(22)


The first report query is `R 1 2 8` asks for the sum modulo 8 of the subtree rooted at 2, when the tree is rooted at 1. The tree looks like 

    1(22)
     \
      \
       2*(22)
       |
       |
       3*(22)
       |
       |
       4*(22)

The sum of the values of nodes 2, 3 and 4 are 

    (22 + 22 + 22) % 8 = 2

The second report query is `R 4 3 9` asks for the sum modulo 9 of the subtree rooted at 3 when the tree is rooted at 4. The tree looks like 

    4(22)
     \
      \
       3*(22)
       |
       |
       2*(22)
       |
       |
       1*(22)

The sum of the values of nodes 3, 2 and 1 are 

    (22 + 22 + 22) % 9 = 3
    
<sub>**Time Limits:**  
C, C++: 4s | Java and other JVM based languages: 10s | Python, Python3 = 45s | Other interpreted Language: 30s | C#, Haskell: 10s | Rest: 3 times of [default](https://www.hackerrank.com/environment).  
</sub>

Input Format:

Output Format:

Sample Input:

Sample Output:

Python 3 starter code:


Reference solution (C++):
    #include <map>
    #include <set>
    #include <list>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <bitset>
    #include <vector>
    #include <ctime>
    #include <cmath>
    #include <cstdio>
    #include <string>
    #include <cstring>
    #include <cassert>
    #include <numeric>
    #include <iomanip>
    #include <sstream>
    #include <fstream>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long       LL;
    typedef pair<int, int>  PII;
    typedef vector<int>     VI;
    typedef vector<LL>      VL;
    typedef vector<PII>     VPII;
    #define MM(a,x) memset(a,x,sizeof(a));
    #define ALL(x)  (x).begin(), (x).end()
    #define P(x)	cerr<<"["#x<<" = "<<(x)<<"]\n"
    #define PP(x,i)	cerr<<"["#x<<i<<" = "<<x[i]<<"]\n"
    #define P2(x,y)	cerr<<"["#x" = "<<(x)<<", "#y" = "<<(y)<<"]\n"
    #define TM(a,b)	cerr<<"["#a" -> "#b": "<<1e3*(b-a)/CLOCKS_PER_SEC<<"ms]\n";
    #define UN(v) sort(ALL(v)), v.resize(unique(ALL(v))-v.begin())
    #define mp make_pair
    #define pb push_back
    #define x first
    #define y second
    struct _ {_() {ios_base::sync_with_stdio(0);}} _;
    template<class A, class B> ostream& operator<<(ostream &o, pair<A, B> t) {o << "(" << t.x << ", " << t.y << ")"; return o;}
    template<class T> void PV(T a, T b) {while(a != b)cout << *a++, cout << (a != b ? "\n" : "\n");}
    template<class T> inline bool chmin(T &a, T b) {return a > b ? a = b, 1 : 0;}
    template<class T> inline bool chmax(T &a, T b) {return a < b ? a = b, 1 : 0;}
    template<class T> string tostring(T x, int len = 0) {stringstream ss; ss << x; string r = ss.str(); if(r.length() < len) r = string(len - r.length(), '0') + r; return r;}
    template<class T> void convert(string x, T& r) {stringstream ss(x); ss >> r;}
    const int inf = 0x3f3f3f3f;
    const long long linf = 0x3f3f3f3f3f3f3f3fLL;
    const int mod = int(1e9) + 7;
    const int N = 111111;

    template <class T>
    struct segment_tree {

        static const int maxn = 4 * 111111;
        T a[maxn], sum[maxn], lazy[maxn];
        int s[maxn], e[maxn];
        int n;
        int md;

    #define ls (x << 1)
    #define rs (x << 1 | 1)

        void init(T* v, int n, int m) {
            this->n = n;
            for(int i = 1; i <= n; i++) a[i] = v[i];
            md = m;
            build(1, n, 1);
        }

        void Up(int x) {
            sum[x] = sum[ls] + sum[rs];
            if(sum[x] >= md) sum[x] -= md;
        }

        void Down(int x) {
            if(lazy[x] == 0) return;
            lazy[ls] += lazy[x];
            lazy[rs] += lazy[x];
            sum[ls]  = (sum[ls] + (LL) lazy[x] * (e[ls] - s[ls] + 1)) % md;
            sum[rs]  = (sum[rs] + (LL) lazy[x] * (e[rs] - s[rs] + 1)) % md;

            if(lazy[ls] >= md) lazy[ls] -= md;
            if(lazy[rs] >= md) lazy[rs] -= md;
            lazy[x] = 0;
        }

        void build(int l, int r, int x) {
            s[x] = l, e[x] = r;
            lazy[x] = 0;
            if(l == r) {
                sum[x] = a[l];
                return;
            }
            int m = (l + r) / 2;
            build(l, m, ls);
            build(m + 1, r, rs);
            Up(x);
        }

        void modify(int L, int R, T c, int l, int r, int x) {
            if(L <= l && r <= R) {
                lazy[x] += c;
                if(lazy[x] >= md) lazy[x] -= md;
                sum[x]  = (sum[x] + (LL)(r - l + 1) * c) % md;
                return;
            }
            Down(x);
            int m = (l + r) / 2;
            if(L <= m) modify(L, R, c, l, m, ls);
            if(R > m)  modify(L, R, c, m + 1, r, rs);
            Up(x);
        }

        T getsum(int L, int R, int l, int r, int x) {
            if(L <= l && r <= R) return sum[x] % md;
            Down(x);
            T res = 0;
            int m = (l + r) / 2;
            if(L <= m) {
                res += getsum(L, R, l, m, ls);
                if(res >= md) res -= md;
            }
            if(R > m)  {
                res += getsum(L, R, m + 1, r, rs);
                if(res >= md) res -= md;
            }
            return res;
        }

        inline void add(int L, int R, T c) {return modify(L, R, c, 1, n, 1);}
        T    getsum(int L, int R)   {return getsum(L, R, 1, n, 1);}
    };

    segment_tree<int> sgt[5];
    typedef long long int ll;
    ll binpow(ll a,ll g,int m)
    {
        a = a%m;
            ll ans=1;
            while(g){
                    if(g&1) ans = ((ll)ans*(ll)a)%m;
                    a = ((ll)a*(ll)a)%m;
                    g>>=1;
            }
            return ans;
    }
    int n, Q;

    vector<int> g[N];

    int father[N];
    int depth[N];
    int s[N];
    int e[N];
    int cnt;

    void dfs(int u, int dep, int par) {
        father[u] = par;
        s[u] = ++cnt;
        depth[u] = dep;
        for(auto v : g[u]) {
            if(v == par) continue;
            dfs(v, dep + 1, u);
        }
        e[u] = cnt;
    }

    int p[N][21];
    void lca_init() {
        for(int i = 1; i <= n; i++) p[i][0] = father[i];
        for(int j = 1; 1 << j < n; j++)
            for(int i = 1; i <= n; i++)
                if(p[i][j - 1] != -1) p[i][j] = p[p[i][j - 1]][j - 1];
    }

    int lca_up(int u, int m) {
        for(int i = 0; i <= 20; i++) if(m & (1 << i)) u = p[u][i];
        return u;
    }

    int lca(int a, int b) {
        if(depth[a] < depth[b]) swap(a, b);
        a = lca_up(a, depth[a] - depth[b]);
        if(a == b) return a;
        for(int i = 20; i >= 0; i--) if(p[a][i] != p[b][i]) a = p[a][i], b = p[b][i];
        return father[a];
    }

    int exp(int x, int n, int m) {
        LL r = 1;
        while(n) {
            if(n & 1) r = r * x % m;
            x = (LL) x * x % m, n >>= 1;
        }
        return r % m;
    }

    int md[5] = {64 * 81 * 25 * 49 * 11 * 13,
                 17 * 19 * 23 * 29 * 31 * 37,
                 43 * 47 * 53 * 59 * 79,
                 61 * 67 * 71 * 73 * 41,
                 83 * 89 * 97 * 101
                };

    int ex[102][102][5];
    int gg[102][5];

    int extended_euclid(int a, int b, int &x, int &y) {
        if(b == 0) {x = 1; y = 0; return a;}
        int d = extended_euclid(b, a % b, y, x);
        y -= a / b * x;
        return d;
    }

    int CRT(int w[], int b[], int len) {
        int ret = 0, n = 1, x, y;
        for(int i = 0; i < len; i++) n *= w[i];
        for(int i = 0; i < len; i++) {
            int m = n / w[i] ;
            int d = extended_euclid(w[i], m, x, y);
            ret = (ret + y * m * b[i]) % n;
        }
        return (n + ret % n) % n;
    }

    int main() {
        /*for(int i = 1; i <= 101; i++)
            for(int j = 1; j <= 101; j++)
                for(int k = 0; k < 5; k++)
                    ex[i][j][k] = exp(i, j, md[k]);*/
        for(int i = 1; i <= 101; i++)
            for(int k = 0; k < 5; k++)
                gg[i][k] = __gcd(i, md[k]);
        scanf("%d",&n);
        //assert(1 <= n && n <= 100000);
        for(int i = 1; i < n; i++) {
            int u, v;
            scanf("%d%d",&u,&v);
        //	assert(1 <= u && u <= n);
        //	assert(1 <= v && u <= n);
            g[u].pb(v);
            g[v].pb(u);
        }

        int d[N] = {};
        for(int i = 0; i < 5; i++) sgt[i].init(d, n, md[i]);

        dfs(1, 0, 0);

        // Is a tree?
        //for(int i = 1; i <= n; i++) if(father[i] == 0) assert(i == 1);

        lca_init();
        scanf("%d",&Q);
        //assert(1 <= Q && Q <= 100000);

        vector<int> ans;
        for(int q = 1; q <= Q; q++) {
            char op;
            int root, sub,  m;
            ll a,b;
            scanf(" %c%d%d",&op,&root,&sub);
            pair<int, int> A(-1, -1), B(-1, -1);
            // linearize
            if(lca(root, sub) != sub) {
                A = mp(s[sub], e[sub]);
            } else if(root == sub) {
                A = mp(1, n);
            } else {
                A = mp(1, n);
                int x = depth[root] - depth[sub] - 1;
                int u = lca_up(root, x);
                B = mp(s[u], e[u]);
            }
            if(op == 'U') {
                scanf("%lld%lld",&a,&b);
                for(int i = 0; i < 5; i++) {
                    //int x = ex[a][b][i];
                    int x = binpow(a,b,md[i]);
                    x = x+binpow(b+1,a,md[i]);
                    if ( x>md[i] ) 	x-= md[i];
                    x = x+binpow(a+1,b,md[i]);
                    if ( x>md[i] ) 	x-= md[i];
                    sgt[i].add(A.x, A.y, x);
                    if(B.x != -1) sgt[i].add(B.x, B.y, md[i] - x);
                }
            } else if(op == 'R') {
                scanf("%d",&m);
                if(m == 1) {ans.pb(0); continue;}
                int res = 0;
                int mm[5], rm1[5], rm2[5], c = 0;
                for(int i = 0; i < 5; i++) {
                    int g = gg[m][i];
                    if(g == 1) continue;
                    mm[c] = g;
                    rm1[c] = sgt[i].getsum(A.x, A.y) % g;
                    if(B.x != -1) rm2[c] = sgt[i].getsum(B.x, B.y) % g;
                    c++;
                }
                res = CRT(mm, rm1, c);
                if(B.x != -1) res -= CRT(mm, rm2, c);
                res = (res % m + m) % m;
                ans.pb(res);
            } else {
                assert(0);
            }
        }
        PV(ALL(ans));
        return 0;
    }