天才逆元少女
这股力量,到底是神还是恶魔呢?——《天才麻将少女》
逆元
在数论中,如果
常常遇到一些题目要求对一个大质数
可以看到,一次取模和步步取模的结果是一样的。
但遇到了除法,那就是小偷碰到了流氓:
为了解决模意义的除法问题,我们引入了逆元。
那么综上所述,我们可以推出这么个不是东西的东西:
实际上,在模
放错了,是这个:
所以这里介绍三种计算逆元的方法。
拓展欧几里得
同余方程实际上就是在求逆元,所以这就是常用的求逆元的方法。
代码如下:
1 | int exgcd (int a. int b, int &x, int &y) // 扩展欧几里得算法 |
费马小定理
费马还是改个名吧,改叫费金花,费羊费牛费猪也比这个好听。风大了可不能走到街上,广告牌一砸下来,别人说,“哟,砸金花了”。
开个玩笑,纯属是个段子,配合一下我们的主题,各位可能知道费马大定理,费马中定理和费马超大定理,但是应该不知道这个。
费马小定理是数论里的重要定理,叙述如下:
若
是质数,且 ,则有 。
从逆元的定义拉倒,可得到
于是对
1 | inline int qpow (int b, int p, int mod) // 慢速幂 |
有没有费马超小定理啊。
线性递推
虽然上面很常用,但是仍然过不了模板题。
所以我们这里介绍逆元的线性递推求法(要求
设:
即:
在模
移项后得到:
则:
然后去把上面的两个式子代入,即:
其实和拓展欧几里得还是有不少相似之处的,可以用记忆化搜索的方法,减少多次查询的时间复杂度(递推即可)。
插播一个悲报:我在准备写这段代码的时候一个没拿稳把驼奶倒进键盘了(哭),等我先清理下键盘先。
回来了,我们继续写代码吧:
1 | int Inv[n] = {0, 1}; |