P4681 [THUSC2015] 平方运算 题解

考虑模数给定,且给定模数最大为 \(9977\)

这启示我们每个数字最多平方取模 \(9976\) 次就会开始重复。但是事实上可能要小得多,于是我们尝试打表验证规律。

打表程序:code

我们验证了确定模数时,所有数字的最多的不超过 \(11\) 次即可进入循环节,且所有循环节的 \(\text{lcm} \le 60\)

事实上,这相当于对于每个 \(x\),连一条 \((x, x^2 \bmod p)\) 的边。

因为会出现循环节,这相当于形成了一棵内向基环树,而对于不同的循环节,我们形成了一个基环树森林。
而验证的东西其实就是环长。

对于找环,可以考虑拓扑排序。

我们想要用线段树维护它,但是当每个数字没有到循环节内时,我们确实没有办法维护这个整体,所以只能暴力。

而当对于某个区间已经全部踏进环内时,我们可以直接对该区间打上 整体在环上移动一步 的标记。

另外,对于一个区间来讲,如果左右区间 \(l, r\) 的循环节已经确定,那么和的循环节长度即为左右 \(l, r\) 循环节的 \(\text{lcm}\)

code

  • 对于复杂度,预处理为 \(O(n \log n)\)
  • 设每个数暴力的次数为 \(c_1\),则暴力部分的复杂度为 \(O(c_1n \log n)\),其中 \(c_1\) 上文已给出,最大为 \(11\)
  • 设循环节长度 \(\text{lcm}\)\(c_2\),线段树上除了叶子节点每个点还会合并一个循环节,所以这部分的复杂度为 \(O(c_2\omega n)\),其中 \(c_2\) 取决于左右子区间循环节长度,上文给出过 \(\text{lcm}\) 最大为 \(60\)\(\omega\) 为线段树节点常数约为 \(4\)
  • 最后是打标记的复杂度,这部分即为 \(O(m \log n)\)

所以总复杂度即为 \(O(c_1n \log n + c_2\omega n + m \log n)\)

posted @ 2024-01-02 09:06  Rainsheep  阅读(139)  评论(0编辑  收藏  举报