Random Numbers Gym - 101466K dfs序+线段树
Posted qldabiaoge
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Random Numbers Gym - 101466K dfs序+线段树相关的知识,希望对你有一定的参考价值。
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 < n, 1 ≤ 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
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
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 }
以上是关于Random Numbers Gym - 101466K dfs序+线段树的主要内容,如果未能解决你的问题,请参考以下文章
Gym 101102J---Divisible Numbers(反推技巧题)
Gym 101128F Sheldon Numbers(网络流)
Codeforces.GYM101612E.Equal Numbers(贪心)