ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

乘法逆元 学习笔记

2020-11-22 08:34:31  阅读:198  来源: 互联网

标签:int mo 笔记 逆元 数组 Time inv 乘法


下面设要求逆元的数是 n ,对 mo 求逆元。

费马小定理

当模数为质数才能用。 逆元为:\(n^{(mo-2)}\%mo\),快速幂可以解决。Time: \(O(log\,mo)\)一般\(mo=1000000007\)或\(998244353\)时,\(log\,mo\)大约是30。

Ex_gcd

模数不为质数也可以用。 求解 exgcd(n,mo,x,y),得到的x就是逆元。Time和费马小定理一样。

注意求解完建议 x=(x+mo)\%mo 。怕x是负数或者大于mo。(但是似乎x不会小于 -mo ,我也不清楚,保险可以加个while什么的)


线性求逆元

递推公式如下:

inv[i]=mo-(mo/i)*inv[mo%i]%mo;

Time:\(O(n)\)

坏处:时间慢,n过大时数组存不下

好处:可以求出1~n所有逆元,所以建议求多次逆元时使用

不过好像如果数组存不下,可以用递归+记忆化(比如你数组能开十万,你就把十万内的逆元记下来,其它的就递归硬算)跑起来挺快的

#include<bits/stdc++.h>
using namespace std;
int mo=998244353;
int n,inv[10000007];

int do_inv(int z){
	if(z<=10000000){//数组能开多大就开多大
		if(inv[z]!=-1)return inv[z];
		inv[z]=mo-(mo/z)*do_inv(mo%z)%mo;
		return inv[z];
	}
	else return mo-(mo/z)*do_inv(mo%z)%mo;
}

int main(){
    memset(inv,-1,sizeof inv);
    inv[1]=1;
    while(cin>>n)cout<<do_inv(n)<<endl;
}

标签:int,mo,笔记,逆元,数组,Time,inv,乘法
来源: https://www.cnblogs.com/BlankAo/p/14018200.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有