乘法逆元
前置芝士:
- 同余
普通逆元
逆元是模意义下的除法。
就是求解同余方程 。
用 exgcd 求解即可。
Code:
#include<iostream>
#include<cstdio>
using namespace std;
void exgcd(int a,int b,int& x,int& y) //拓展欧几里得
{
if (!b){x=1;y=0;return ;}
exgcd(b,a%b);
int tmp=x;x=y;y=tmp-a/b*y;
}
int main()
{
int a,b,x,y;
scanf("%d %d",&a,&b);
exgcd(a,b,x,y);
printf("%d",(x+b)%b);//转 正
return 0;
}
素数的逆元
我们知道素数是有费马小定理的:
若 为素数,则 。
当且仅当 时:
然后我们用后面的式子同除以一个 ,可以得到 ,所以我们只要求出 就可以了,用快速幂求解即可。
Code:
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
ll qpow(ll x,ll y,ll mod) //快速幂
{
ll ans=1,base=x;
while (y)
{
if (y&1) ans*=base;
base*=base;y>>=1;
}
return ans;
}
int main()
{
ll x,p;
scanf("%lld %lld",&x,&p);
printf("%lld",qpow(x,p-2,p));
return 0;
}
线性筛逆元
让人感受线性筛的奥妙
线性筛肯定是 的嘛。
首先我们设 ,然后可以知道 (因为 ,所以 )。
然后我们两边同乘 ,就得到 ,移项得到 。
我们可以知道 ,所以我们得到公式:
#include<iostream>
#include<cstdio>
using namespace std;
const int N=10001;
typedef long long ll;
ll inv[N];
void GetInv(ll n,ll p)
{
for (int i=2;i<=n;i++)
inv[i]=(-(p/i)*inv[p%i]%p+p)%p;
}
线性筛阶乘逆元
也就是线性筛 。
我们设 表示 的逆元。
我们可以轻易知道 ,我们同乘 就变成了,,所以我们可以得到:
所以我们先求出 的逆元,再倒推回来即可。
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
ll inv[3000100];
void GetFactInv()
{
inv[1]=inv[0]=1;
for (int i=1;i<=n;i++) //求阶乘
inv[i]=(inv[i-1]*i)%p;
inv[n]=GetInv(inv[n],p); //求n!的逆元
for (int i=n-1;i>=1;i--)//倒推
inv[i]=(inv[i+1]*(i+1))%p;
return 0;
}
以下是博客签名,正文无关
本文来自博客园,作者:yspm,转载请注明原文链接:https://www.cnblogs.com/CDOI-24374/p/12853993.html
版权声明:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0)进行许可。看完如果觉得有用请点个赞吧 QwQ
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】