题意
给出一个模\(p\)(\(p\)是素数)意义下的序列,支持两种操作:
- 区间乘一个数;
- 询问一个区间的元素构成的群的大小。
保证序列中的数时时刻刻不为\(0\)。
题解
一道好题……sb了好久。
第一个想法显然是先找到一个原根\(g\),再取指标进行运算。
然后对于一个区间\(g ^ {k_l}, g ^ {k_{l + 1}}, \ldots, g ^ {k_r}\),生成群的生成元\(\omega\)为\(g ^ {(\gcd{k_l, k_{l + 1}, \ldots, k_r, p - 1})}\),则群的大小为\(\frac{p - 1}{ind_g(\omega)}\)。
看这个\(\gcd\),因为要区间修改,所以要维护原序列和原序列的差分两个数组,因为
\[ \gcd(x_1, x_2, \ldots, x_n) = \gcd(x_1, x_2 - x_1, \ldots, x_n - x_{n - 1}) \]
这样便把区间修改变成单点修改。
复杂度是\(\mathcal O((n + q) \sqrt {(n + q) p} + q \log ^ 2 n)\),因为要bsgs求指标(我tmbsgs块大小还写挂了)。
然而这样是过不了的。那咋整啊?
XZA说指标的信息有冗余,实际上只需要求阶即可(求阶是\(\mathcal O(\log ^ 2 p)\)的)。然而当时并没有理解这句话的意思,尽管感性理解好像是这回事。
考虑直接用阶做。
假设我们已经知道了区间\([l, r]\)中每个元素的阶,那么如何求其生成群的大小?考虑两两合并。
对于一个阶为\(a\)的元素和一个阶为\(b\)的元素,其生成的群可分别表示为\(<g ^ {\frac{p - 1}{a}}>, <g ^ {\frac{p - 1}{b}}>\)。
那么合并之后,群可表示为\(<g ^ {\gcd{(\frac{p - 1}{a}}, \frac{p - 1}{b})}>\)。则新的群的大小为\(\frac{p - 1}{\gcd{(\frac{p - 1}{a}}, \frac{p - 1}{b})}\)。
简单运算一下,发现就等于\(\text{lcm} (a, b)\)。
这其中用到了一个很基础的定理:循环群的大小等于其生成元的阶。