K. Random Numbers(Gym 101466K + 线段树 + dfs序 + 快速幂 + 唯一分解)
Posted dillonh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了K. Random Numbers(Gym 101466K + 线段树 + dfs序 + 快速幂 + 唯一分解)相关的知识,希望对你有一定的参考价值。
题目链接:http://codeforces.com/gym/101466/problem/K
题目:
题意:
给你一棵有n个节点的树,根节点始终为0,有两种操作:
1.RAND:查询以u为根节点的子树上的所有节点的权值的乘积x,及x的因数个数。
2.SEED:将节点u的权值乘以x。
思路:
比赛时少看了因数不大于13这句话,然后本题难度增加数倍,肝了两个小时都没肝出来,对不起队友啊,今天的组队训练赛实力背锅……
这题一眼线段树,由于是对一棵子树进行处理,因此我们采用常规套路,借助dfs序将子树变成区间。不过因为权值的乘积太大,还要取模,一个数取模后因数个数也会发生变化,所以我们肯定不能用它的权值来进行建树,因而我们可以将思路进行转化,先将它的每个节点的权值进行唯一分解,对指数进行建树。
对于最后的答案,第一个乘积x很容易求,用快速幂对2,3,5,7,11,13这六个素数进行处理即可。而第二个答案,我们根据数论知识知道它的结果是∏(1+ci),其中ci为某个因数pi的指数。
代码实现如下:
1 #include <set> 2 #include <map> 3 #include <queue> 4 #include <stack> 5 #include <cmath> 6 #include <bitset> 7 #include <cstdio> 8 #include <string> 9 #include <vector> 10 #include <cstdlib> 11 #include <cstring> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 16 typedef long long ll; 17 typedef pair<ll, ll> pll; 18 typedef pair<ll, int> pli; 19 typedef pair<int, ll> pil;; 20 typedef pair<int, int> pii; 21 typedef unsigned long long ull; 22 23 #define lson i<<1 24 #define rson i<<1|1 25 #define lowbit(x) x&(-x) 26 #define bug printf("********* "); 27 #define debug(x) cout<<"["<<x<<"]" <<endl; 28 #define FIN freopen("D://code//in.txt", "r", stdin); 29 #define IO ios::sync_with_stdio(false),cin.tie(0); 30 31 const double eps = 1e-8; 32 const int mod = 1e9 + 7; 33 const int maxn = 1e5 + 7; 34 const int mx = 1e4 + 7; 35 const double pi = acos(-1); 36 const int inf = 0x3f3f3f3f; 37 const ll INF = 0x3f3f3f3f3f3f3f3f; 38 39 int n, tot, q, u, v, x, p, a, b; 40 char op[10]; 41 int prime[6] = {2, 3, 5, 7, 11, 13}, cnt[6], ans[6]; 42 int val[maxn], head[maxn], s[maxn], t[maxn]; 43 44 struct edge { 45 int v, next; 46 }ed[maxn]; 47 48 struct node { 49 int l, r; 50 int num[6]; 51 }segtree[maxn<<2]; 52 53 void addedge(int u, int v) { 54 ed[tot].v = v; 55 ed[tot].next = head[u]; 56 head[u] = tot++; 57 } 58 59 void dfs(int u) { 60 s[u] = ++x; 61 for(int i = head[u]; ~i; i = ed[i].next) { 62 int v = ed[i].v; 63 dfs(v); 64 } 65 t[u] = x; 66 } 67 68 void push_up(int i) { 69 for(int j = 0; j < 6; j++) { 70 segtree[i].num[j] = (segtree[lson].num[j] + segtree[rson].num[j]) % mod; 71 } 72 } 73 74 void build(int i, int l, int r) { 75 segtree[i].l = l, segtree[i].r = r; 76 for(int j = 0; j < 6; j++) { 77 segtree[i].num[j] = 0; 78 } 79 if(l == r) { 80 for(int j = 0; j < 6; j++) { 81 if(val[l] % prime[j] == 0) { 82 while(val[l] % prime[j] == 0) { 83 segtree[i].num[j]++; 84 val[l] /= prime[j]; 85 } 86 } 87 } 88 return; 89 } 90 int mid = (l + r) >> 1; 91 build(lson, l, mid); 92 build(rson, mid + 1, r); 93 push_up(i); 94 } 95 96 void update(int i, int pos, int cnt[]) { 97 if(segtree[i].l == pos && segtree[i].r == pos) { 98 for(int j = 0; j < 6; j++) { 99 segtree[i].num[j] = (segtree[i].num[j] + cnt[j]) % mod; 100 } 101 return; 102 } 103 int mid = (segtree[i].l + segtree[i].r) >> 1; 104 if(pos <= mid) update(lson, pos, cnt); 105 else update(rson, pos, cnt); 106 push_up(i); 107 } 108 109 int Mod_Pow(int x, int n) { 110 int res = 1; 111 while(n) { 112 if(n & 1) res = (ll) res * x % mod; 113 x = (ll)x * x % mod; 114 n >>= 1; 115 } 116 return res; 117 } 118 119 void query(int i, int l, int r, int ans[]) { 120 if(segtree[i].l == l && segtree[i].r == r) { 121 for(int j = 0; j < 6; j++) { 122 ans[j] += segtree[i].num[j]; 123 } 124 return; 125 } 126 int mid = (segtree[i].l + segtree[i].r) >> 1; 127 if(r <= mid) query(lson, l, r, ans); 128 else if(l > mid) query(rson, l, r, ans); 129 else { 130 query(lson, l, mid, ans); 131 query(rson, mid + 1, r, ans); 132 } 133 } 134 135 int main() { 136 //FIN; 137 tot = x = 0; 138 memset(head, -1, sizeof(head)); 139 scanf("%d", &n); 140 for(int i = 1; i < n; i++) { 141 scanf("%d%d", &u, &v); 142 u++, v++; 143 addedge(u, v); 144 } 145 dfs(1); 146 for(int i = 1; i <= n; i++) { 147 scanf("%d", &p); 148 val[s[i]] = p; 149 } 150 build(1, 1, n); 151 scanf("%d", &q); 152 while(q--) { 153 scanf("%s", op); 154 if(op[0] == ‘R‘) { 155 scanf("%d", &a); 156 a++; 157 for(int i = 0; i < 6; i++) ans[i] = 0; 158 query(1, s[a], t[a], ans); 159 ll cnt1 = 1, cnt2 = 1; 160 for(int i = 0; i < 6; i++) { 161 cnt2 = (cnt2 * ((1 + ans[i]) % mod)) % mod; 162 cnt1 = (cnt1 * Mod_Pow(prime[i], ans[i])) % mod; 163 } 164 printf("%lld %lld ", cnt1, cnt2); 165 } else { 166 scanf("%d%d", &a, &b); 167 a++; 168 for(int j = 0; j < 6; j++) { 169 cnt[j] = 0; 170 if(b % prime[j] == 0) { 171 while(b % prime[j] == 0) { 172 cnt[j]++; 173 b /= prime[j]; 174 } 175 } 176 } 177 update(1, s[a], cnt); 178 } 179 } 180 return 0; 181 }
以上是关于K. Random Numbers(Gym 101466K + 线段树 + dfs序 + 快速幂 + 唯一分解)的主要内容,如果未能解决你的问题,请参考以下文章
gym101102J Divisible Numbers(预处理)
GYM 102501 K. Birdwatching(bfs,思维)
GYM 102501 K. Birdwatching(bfs,思维)
GYM 100792 K. King's Rout(topo排序+逆向思维)