K. Random Numbers(Gym 101466K + 線段樹 + dfs序 + 快速冪 + 唯一分解)
阿新 • • 發佈:2018-08-19
-s targe pll nbsp nod 根節點 end head 分享
題目鏈接: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("*********\n"); 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\n", 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序 + 快速冪 + 唯一分解)