乘法逆元 线性递推阶乘求逆元、费马小定理、普适线性求逆元 欧拉定理结论
时间:2022-07-26
本文章向大家介绍乘法逆元 线性递推阶乘求逆元、费马小定理、普适线性求逆元 欧拉定理结论,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
Definition
对于一个数 x 和一个模数 p,若存在一个数字 y,满足
则称 y 是 x 在模 p 意义下的逆元,记做
。
一个数字逆元在模意义下的运算中可以完全取代该数字的倒数。例如
,其中
代表 y的逆元。
单个数求逆元有扩展欧几里得、费马小定理 复杂度logn
对于竞赛中,一般常用的是费马小定理,因为模数一般是质数
具体如下:
根据欧拉定理
其中
为欧拉函数,
表示小于 p 的正整数中与 p 互质的数的个数。
等式两侧同乘
可以得到
显然当 p 是一个质数时,
,这时可以 O(1) 算出
的值,即可用快速幂 求出 x的逆元。这个算法好写好记,常数也较小。一般当 p 为 int
范围内的质数时选择此算法。当 p 不在 int
范围内时,由于快速幂时需要两个 long long
相乘,会爆精度。
至于证明,自行百度,会用就行~
线性递推阶乘求逆元结论:
其中p为模数,inv[i]表示数i的逆元
对了,欧拉定理有个好用的结论,需要记下来:
通过这个式子可以有效的简化模数
最一般的,给你n个数:
我们设数组a的各项是:
则其逆元可表示为:
则
其中pre[i]表示前i个数相乘,suf[i]表示从第n个数开始倒回去乘到第i个数,(模p意义下)
这样o(n)我们就可以求出这些数的逆元了~
附上两题模板题:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rg register ll
#define inf 2147483647
#define lb(x) (x&(-x))
ll sz[200005],n;
template <typename T> inline void read(T& x)
{
x=0;char ch=getchar();ll f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}x*=f;
}
inline ll query(ll x){ll res=0;while(x){res+=sz[x];x-=lb(x);}return res;}
inline void add(ll x,ll val){while(x<=n){sz[x]+=val;x+=lb(x);}}//第x个加上val
ll p,inv[5000005]={0,1};
int main()
{
cin>>n>>p;
cout<<1<<endl;
for(rg i=2;i<=n;i++)
{
inv[i]=p-(p/i)*inv[p%i]%p;
printf("%lldn",inv[i]);
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rg register ll
#define inf 2147483647
#define lb(x) (x&(-x))
template <typename T> inline void read(T& x)
{
x=0;char ch=getchar();ll f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}x*=f;
}
ll a[5000005],sum,suf[5000005],n,p,k,pre;
inline ll qp(ll x,ll m)
{
ll res=1;
while(m)
{
if(m&1)res=res*x%p;
x=x*x%p;
m>>=1;
}
return res%p;
}
inline ll in(ll x)
{
return qp(x,p-2);
}
int main()
{
cin>>n>>p>>k;
ll k1=k;
pre=1,suf[n+1]=1;
for(rg i=1;i<=n;i++)read(a[i]);
for(rg i=n;i>=1;i--)suf[i]=suf[i+1]*a[i]%p;
ll zong=in(suf[1]);
for(rg i=1;i<=n;i++)sum+=zong%p*pre%p*suf[i+1]%p*k1,sum%=p,k1=k1*k%p,pre=pre*a[i]%p;
cout<<sum<<endl;
return 0;
}
- 从APM角度上看:NoSQL和关系数据库并无不同
- 事故记录-过多进程致使CPU卡死
- Flash/Flex学习笔记(54):迷你滚动条ScrollBar
- linux下正向代理/反向代理/透明代理使用说明
- 万达网科年底集体裁员?公司回应仅是业务调整
- 两个四字母域名均以五位数被交易
- Flash/Flex学习笔记(15):FMS 3.5之远程共享对象(Remote Shared Object)
- Android Fragment完全解析
- Centos下堡垒机Jumpserver V3.0环境部署完整记录(2)-配置篇
- Flash/Flex学习笔记(53):利用FMS快速创建一个文本聊天室
- 28家银行用户体验调研报告:洞见银行业的“进化论”
- 性能计数器数据收集服务
- SQL SERVER 内存分配及常见内存问题 DMV查询
- 6 利用Docker .NET应用程序模板制作您的容器应用程序(第2部分)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- OpenWRT配置Webdav(s)共享文件 By HKL,
- OpenWRT配置Apache Webdav By HKL,
- 我向面试官讲解了单例模式,他对我竖起了大拇指
- 47 张图带你 MySQL 进阶!!!
- 新特性解读 | InnoDB-Cluster 扫盲-日常运维
- Laravel 框架实现无限极分类
- 这样设置IDEA,让你爽到飞起!
- 这些年,我写过的BUG(一)
- Selenium处理下拉列表
- 掌握好这几个css属性,少写100行js代码
- 计算机基础知识总结与操作系统 PDF 下载
- Kafka工作流程及文件存储机制
- JS破解初探,折腾到头秃的美拍视频采集下载
- 去哪儿景点信息爬取并使用Django框架网页展示
- Kubernetes v1.15.3 升级到 v1.18.5 心得