【个人总结】常用 OI 技巧汇总

严格来说,这可能并不能算作学习笔记,但还是这么算了。

这篇文章可能全程比较沙雕,所以对于风格不要过度在意。


咳咳,上面都是作者的废话。下面进入正题。

这篇文章主要介绍的是一些比较常用(?)的 OI 小技巧。这可能有助于在 OI 中获得优势(?\(\times 2\))。

文章内容按照字典序排序。


\(\textrm{I}\). 龟速乘

这是一个极其常用的小技巧,原因比较简单,那就是比赛时常用。

通常来说,一道题的答案如果过大的话,有两种方案——高精度和取模。

但是,由于前一段时间(?\(\times 3\))的接连不断的高精度把人弄得有一点烦,加上高精度本身也有复杂度一说,所以并不是一个理想的评测算法的工具。

取而代之,很多题目都会在题目末尾加上一句「答案对 \(998244353\) 取模」或类似的话。一来是解决内置变量存储上限,二来则是忽略计算复杂度。

但是,当模数极其接近变量上限边缘时,乘法就变得岌岌可危,比如:计算 \(123456789876\times 5432123456789 \bmod{192837465647389}\) 这种类似的东西。

咳咳,于是乎,我们就发明了一种很棒的东西。这可以解决模数上限的问题,但不可避免地会出现一点常数,虽然只有 \(O(\log n)\)。这就是龟速乘。

那说了这么多,龟速乘到底是个什么东西呢?????说白了就是快速幂。为什么?

多次连乘是乘方运算,多次连加就是乘法运算

也就是说吧乘法变成一次次的加法而达到其目的,也就不可避免地有 \(O(\log n)\) 的多余复杂度。

但是!这并不是唯一的解决办法,网上还有通过 long double 来卡精度从而达到 \(O(1)\) 的龟速乘,这里不再赘述。


\(\textrm{II}\). 快速幂
快速幂是位运算的应用中的一种,可以在 \(O(\log n)\) 的时间内计算形如 \(a^b\ (b\in \mathbb{N}^{*})\) 的算法。

简单来说,就是计算一个数列 \(\left<c_0,c_1,c_2,\cdots,c_k\right>\),使得 \(b=\sum\limits_{i=0}^k \left(c_i\times 2^i\right)\),这可以通过二进制分解在 \(O(\log n)\) 的时间内解决。

接下来是算法的精髓——注意到 \(2^i=2^{i-1} + 2^{i-1}\),即 \(u^{2^i}=\left(u^{2^{i-1}}\right)^2\)

\(\therefore\quad a^b=\prod\limits_{i=0}^k a^{2^i}\)

而预处理 \(a^{2^i}\)\(O(k)\sim O(\log n)\),总体就是 \(O(\log n)\)

猜你喜欢

转载自www.cnblogs.com/5ab-juruo/p/self-conclution-about-common-tricks-in-OI.html
OI