Random Numbers Gym

Tamref love random numbers, but he hates recurrent relations, Tamref thinks that mainstream random generators like the linear congruent generator suck. That's why he decided to invent his own random generator.

As any reasonable competitive programmer, he loves trees. His generator starts with a tree with numbers on each node. To compute a new random number, he picks a rooted subtree and multiply the values of each node on the subtree. He also needs to compute the number of divisors of the generated number (because of cryptographical applications).

In order to modify the tree (and hence create different numbers on the future), Tamref decided to perform another query: pick a node, and multiply its value by a given number.

Given a initial tree T, where Tu corresponds to the value on the node u, the operations can be summarized as follows:

  • RAND: Given a node u compute  and count its divisors, where T(u) is the set of nodes that belong to the subtree rooted at u.
  • SEED: Given a node u and a number x, multiply Tu by x.

Tamref is quite busy trying to prove that his method indeed gives integers uniformly distributed, in the meantime, he wants to test his method with a set of queries, and check which numbers are generated. He wants you to write a program that given the tree, and some queries, prints the generated numbers and count its divisors.

Tamref has told you that the largest prime factor of both Tu and x is at most the Tamref's favourite prime: 13. He also told you that the root of T is always node 0.

The figure shows the sample test case. The numbers inside the squares are the values on each node of the tree. The subtree rooted at node 1 is colored. The RAND query for the subtree rooted at node 1 would generate 14400, which has 63 divisors.

Input

The first line is an integer n (1 ≤ n ≤ 105), the number of nodes in the tree T. Then there are n - 1 lines, each line contains two integers u and v (0 ≤ u, v < n) separated by a single space, it represents that u is a parent of v in T. The next line contains n integers, where the i - th integer corresponds to Ti (1 ≤ Ti ≤ 109). The next line contains a number Q (1 ≤ Q ≤ 105), the number of queries. The final Q lines contain a query per line, in the form "RAND u" or "SEED u x" (0 ≤ u < n1 ≤ x ≤ 109).

Output

For each RAND query, print one line with the generated number and its number of divisors separated by a space. As this number can be very long, the generated number and its divisors must be printed modulo 109 + 7.

Example

Input
8
0 1
0 2
1 3
2 4
2 5
3 6
3 7
7 3 10 8 12 14 40 15
3
RAND 1
SEED 1 13
RAND 1
Output
14400 63
187200 126

题意:

  给你一棵有n个节点的树,根节点始终为0,有两种操作:

    1.RAND:查询以u为根节点的子树上的所有节点的权值的乘积x,及x的因数个数。

    2.SEED:将节点u的权值乘以x。

看清楚题目啊  素因子最大为13

知道这个用dfs序处理一下 然后建立线段树就OK了

这题还用来 唯一分解定理  https://www.cnblogs.com/qldabiaoge/p/8647130.html

再用快速幂处理一下就搞定了

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <queue>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <set>
  7 #include <iostream>
  8 #include <map>
  9 #include <stack>
 10 #include <string>
 11 #include <vector>
 12 #include <bits/stdc++.h>
 13 #define  pi acos(-1.0)
 14 #define  eps 1e-6
 15 #define  fi first
 16 #define  se second
 17 #define  lson        l,m,rt<<1
 18 #define  rson        m+1,r,rt<<1|1
 19 #define  rtl         rt<<1
 20 #define  rtr         rt<<1|1
 21 #define  bug         printf("******
")
 22 #define  mem(a,b)    memset(a,b,sizeof(a))
 23 #define  fuck(x)     cout<<"["<<x<<"]"<<endl
 24 #define  f(a)        a*a
 25 #define  sf(n)       scanf("%d", &n)
 26 #define  sff(a,b)    scanf("%d %d", &a, &b)
 27 #define  sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
 28 #define  sffff(a,b,c,d) scanf("%d %d %d %d", &a, &b, &c, &d)
 29 #define  pf          printf
 30 #define  FRE(i,a,b)  for(i = a; i <= b; i++)
 31 #define  FREE(i,a,b) for(i = a; i >= b; i--)
 32 #define  FRL(i,a,b)  for(i = a; i < b; i++)
 33 #define  FRLL(i,a,b) for(i = a; i > b; i--)
 34 #define  FIN         freopen("DATA.txt","r",stdin)
 35 #define  gcd(a,b)    __gcd(a,b)
 36 #define  lowbit(x)   x&-x
 37 #pragma  comment (linker,"/STACK:102400000,102400000")
 38 using namespace std;
 39 typedef long long LL;
 40 typedef unsigned long long ULL;
 41 const int INF = 0x7fffffff;
 42 const LL LLINF = 0x3f3f3f3f3f3f3f3fll;
 43 const int maxn = 1e6 + 10;
 44 const int mod = 1e9 + 7;
 45 int n, m, x, y, tot, dfscnt, head[maxn], L[maxn], R[maxn], val[maxn];
 46 int prime[6] = {2, 3, 5, 7, 11, 13}, cnt[10], ans[10];
 47 struct Edge {
 48     int v, nxt;
 49 } edge[maxn << 2];
 50 void init() {
 51     tot = 0;
 52     mem(head, -1);
 53 }
 54 void add(int u, int v) {
 55     edge[tot].v = v;
 56     edge[tot].nxt = head[u];
 57     head[u] = tot++;
 58 }
 59 void dfs(int u, int fa) {
 60     L[u] = ++dfscnt;
 61     for (int i = head[u]; ~i ; i = edge[i].nxt) {
 62         int v = edge[i].v;
 63         if (v != fa) dfs(v, u);
 64     }
 65     R[u] = dfscnt;
 66 }
 67 struct node {
 68     int l, r, num[6];
 69     int mid() {
 70         return (l + r) >> 1;
 71     }
 72 } tree[maxn << 2];
 73 void pushup(int rt) {
 74     for (int i = 0 ; i < 6 ; i++)
 75         tree[rt].num[i] = (tree[rtl].num[i] + tree[rtr].num[i]) % mod;
 76 }
 77 void build(int l, int r, int rt) {
 78     tree[rt].l = l, tree[rt].r = r;
 79     mem(tree[rt].num, 0);
 80     if (l == r) {
 81         for (int i = 0 ; i < 6 ; i++) {
 82             while(val[l] % prime[i] == 0) {
 83                 val[l] /= prime[i];
 84                 tree[rt].num[i]++;
 85             }
 86         }
 87         return ;
 88     }
 89     int m = (l + r) >> 1;
 90     build(l, m, rtl);
 91     build(m + 1, r, rtr);
 92     pushup(rt);
 93 }
 94 void update(int pos, int rt) {
 95     if (tree[rt].l == pos && tree[rt].r == pos) {
 96         for (int i = 0 ; i < 6 ; i++)
 97             tree[rt].num[i] = (tree[rt].num[i] + cnt[i]) % mod;
 98         return ;
 99     }
100     int m = tree[rt].mid();
101     if (pos <= m) update(pos, rtl);
102     else update(pos, rtr);
103     pushup(rt);
104 }
105 void query(int L, int R, int rt) {
106     if (tree[rt].l == L && tree[rt].r == R) {
107         for (int i = 0 ; i < 6 ; i++)
108             ans[i] = (ans[i] + tree[rt].num[i]) % mod;
109         return ;
110     }
111     int m = tree[rt].mid();
112     if (R <= m) query(L, R, rtl);
113     else if (L > m) query(L, R, rtr);
114     else {
115         query(L, m, rtl);
116         query(m + 1, R, rtr);
117     }
118 }
119 int expmod(int a, int b) {
120     int ret = 1;
121     while(b) {
122         if(b & 1) ret = 1LL * ret * a % mod;
123         a = 1LL * a * a % mod;
124         b = b >> 1;
125     }
126     return ret;
127 }
128 int main() {
129     sf(n);
130     init();
131     for (int i = 1 ; i < n ; i++) {
132         int u, v;
133         sff(u, v);
134         u++, v++;
135         add(u, v);
136         add(v, u);
137     }
138     dfs(1, -1);
139     for (int i = 1 ; i <= n ; i++) {
140         sf(x);
141         val[L[i]] = x;
142     }
143     build(1, n, 1);
144     sf(m);
145     while(m--) {
146         char op[10];
147         scanf("%s", op);
148         if (op[0] == 'R') {
149             sf(x);
150             x++;
151             mem(ans, 0);
152             query(L[x], R[x], 1);
153             LL ans1 = 1, ans2 = 1;
154             for (int i = 0 ; i < 6 ; i++) {
155                 ans1 = (ans1 * expmod(prime[i], ans[i]) % mod) % mod;
156                 ans2 = (ans2*((ans[i]+1)%mod)) % mod;
157             }
158             printf("%lld %lld
", ans1, ans2);
159         } else {
160             sff(x, y);
161             x++;
162             for (int i = 0 ; i < 6 ; i++) {
163                 cnt[i] = 0;
164                 while(y % prime[i] == 0) {
165                     cnt[i]++;
166                     y /= prime[i];
167                 }
168             }
169             update(L[x], 1);
170         }
171     }
172     return 0;
173 }
原文地址:https://www.cnblogs.com/qldabiaoge/p/9514541.html