传送门
Description
现在有一个数 \(x\),初始值为 \(1\)。有 \(Q\) 次操作,操作有两种:
\(1\) \(m\):将 \(x\) 变为 \(x \times m\),并输出 \(x \bmod M\)
\(2\) \(pos\):将 \(x\) 变为 \(x\) 除以第 \(pos\) 次操作所乘的数(保证第 \(pos\) 次操作一定为类型 \(1\),对于每一个类型 \(1\) 的操作至多会被除一次),并输出 \(x \bmod M\)。
每个测试点共有 \(T\) 组输入。
Constraints
对于 \(20\%\) 的数据,\(1 \le Q \le 500\)。
对于 \(100\%\) 的数据,\(1 \le Q \le 10^5\),\(T \le 5, M \le 10^9\),\(0 < m \leq 10^9\)。
Solution 0 \(TLE\) or \(WA\)
扫一眼题目,这题似乎能用模拟解决。
然而我们发现,若使用高精度乘法,时间必然会不够,直接吃一个 TLE。
同时,由于出现了除法,所以在取模时应当想到逆元,但是 \(M\) 并不一定为质数,逆元也不可做。
Solution 1
注意看题目里我加粗的那行字,题中保证了每次乘操作在后面的除操作中至多只用一次。
想想后面的除操作,是不是就相当于将前面的乘操作抵消掉呢?(抵消掉,意思就是把乘操作的值变回 \(1\))
把“时间”(操作次数) \(i\) 抽象成一个个初始为 \(1\) 点,乘操作就是把该“时间” \(i\) 的值修改为乘上的值,除操作就是把这个位置上的值变为 \(1\),则每次询问的答案就是从 \(1\) 位置到 \(i\) 所有数之积对 \(M\) 取模。
可以看出,这就是单点修改和区间查询,自然能够想到使用树状数组或线段树维护。
Code
最近在学线段树,就拿线段树来写了~
注意一开始整棵线段树要全赋为 \(1\),注意开 long long。
// by youyou2007 in 2022.
#include
#include
#include
#include
#include
#include
#include
#include
#include