P4588 [TJOI2018]数学计算 题解
旅行传送门:https://www.luogu.com.cn/problem/P4588
题目描述
小豆现在有一个数 x,初始值为 1。小豆有 Q 次操作,操作有两种类型:
1 m
:将 x 变为 x * m,并输出 x mod M
2 pos
:将 x 变为 x 除以第 pos 次操作所乘的数(保证第 pos 次操作一定为类型 1,对于每一个类型 1 的操作至多会被除一次),并输出 x mod M。
输入格式
一共有 t 组输入。
对于每一组输入,第一行是两个数字 Q,M。
接下来 Q 行,每一行为操作类型 op,操作编号或所乘的数字 m(保证所有的输入都是合法的)。
输出格式
对于每一个操作,输出一行,包含操作执行后的 x mod M 的值。
输入输出样例
输入 #1
1 10 1000000000 1 2 2 1 1 2 1 10 2 3 2 4 1 6 1 7 1 12 2 7
输出 #1
2 1 2 20 10 1 6 42 504 84
说明/提示
对于 20% 的数据,1 ≤ Q ≤ 500。
对于 100% 的数据,1 ≤ Q ≤ 10^5,t ≤ 5,M ≤ 10^9。
解题思路
第一眼看去,就只对一个数进行操作,这哪是甚么线段树的题,直接上暴力模拟不就完事了(上了就去见祖宗,哪怕开long long也直接亲ma炸穿)(虽然纯当作数论题做也不是不行)。
但转念一想,蓝题不可能这么水,重新审题,题目中有两个操作,一是x乘以一个值,另一个是x除以之前乘过的某个值;乘以一个数又除以一个数,相当于啥也没干,也就可以看成是回溯操作。那么我们不妨以时间为轴建立一棵范围为[1,Q]的线段树,第k个叶子节点的序号表示这是第pos次操作,其存储的值表示x在这次操作中乘以的数。此时第一种操作变为给当前叶节点赋值m,第二种操作变为令第pos个叶节点的值回溯至1,根节点的值就是每次操作执行后x的值。
总的来说是道很有意思的题_(:з」∠)_
AC代码
1 #include <bits/stdc++.h> 2 #define FOR(i, j, k) for (int i = (j); i <= (k); i++) 3 #define MAXQ 100000 + 10 4 5 typedef long long ll; 6 7 ll t, q, mod; 8 ll tree[MAXQ << 2]; 9 10 ll read() 11 { 12 ll x = 0, f = 1; 13 char ch = getchar(); 14 while (ch < '0' || ch > '9') 15 { 16 if (ch == '-') 17 f = -1; 18 ch = getchar(); 19 } 20 while (ch >= '0' && ch <= '9') 21 { 22 x = x * 10 + ch - '0'; 23 ch = getchar(); 24 } 25 return x * f; 26 } 27 28 void build(ll k, ll l, ll r) 29 { 30 tree[k] = 1; 31 if (l == r) 32 return; 33 ll mid = (l + r) >> 1; 34 build(k << 1, l, mid); 35 build(k << 1 | 1, mid + 1, r); 36 } 37 38 void update(ll k, ll l, ll r, ll pos, ll x) 39 { 40 if (l == r) 41 { 42 tree[k] = x; 43 return; 44 } 45 ll mid = (l + r) >> 1; 46 if (pos <= mid) 47 update(k << 1, l, mid, pos, x); 48 else 49 update(k << 1 | 1, mid + 1, r, pos, x); 50 tree[k] = ((tree[k << 1] % mod) * (tree[k << 1 | 1] % mod)) % mod; 51 } 52 53 int main(int argc, char const *argv[]) 54 { 55 t = read(); 56 while (t--) 57 { 58 q = read(), mod = read(); 59 build(1, 1, q); 60 FOR(i, 1, q) 61 { 62 ll op = read(); 63 if (op == 1) 64 { 65 ll m = read(); 66 update(1, 1, q, i, m); 67 printf("%lld\n", tree[1] % mod); 68 } 69 else 70 { 71 ll pos = read(); 72 update(1, 1, q, pos, 1); 73 printf("%lld\n", tree[1] % mod); 74 } 75 } 76 } 77 return 0; 78 }