模运算 及 逆元
1、四则运算均可进行取模运算(mod)。
在加法(与乘法相同)的取模运算中,可以写作
但是减法的取模运算, 在计算机中的运算为 ,但正确的结果应为 ,所以减法取模为
异或的取模运算
然而除法的取模却大不相同,因为对于
此处引入 逆元 的概念,来解决对于除法的取模问题。
2、在取模意义下的除法——逆元。
概念:单位元 与 逆元
在一个集合中,对于某种运算 *(注意:这里代表通用运算的表示符号,并不是特指乘法),如果对于任何的集合元素 ,和元素 运算,得到还是集合元素 本身,则称 为这个运算下的单位元。
逆元素(逆元,指一个可以取消另一给定元素运算的元素)在一个集合中,对于某种运算 *,如果任意两个元素的运算结果等于单位元,则称这两个元素互为逆元。
加法的单位元为 ,其加法逆元为相反数。
乘法的单位元为 ,其乘法逆元为倒数。
在模运算中,
对于同余方程 , 我们称 是 在模 意义下的逆元,其单位元为 。
前提:由裴蜀定理(或贝祖定理)可知,当且仅当 时, 在模 的情况下有逆元。
解决取模意义下的除法:,即 在模 的意义下,一个数 有逆元除以 。( 是指 的逆元)
如何求逆元?(如何解决取模意义下的除法?)
答:扩展欧几里得、费马小定理、欧拉定理 . . .
i、扩展欧几里得求逆元
扩展欧几里得是用于求解不定方程 的一组解的算法,但对于同余方程 也可以写作不定方程的形式:
由此可以求得 的值,即逆元的值。
int exgcd(int a, int b, int &x, int &y)
{
if (b == 0)
{
x = 1, y = 0;
return a;
}
int r = exgcd(b, a%b, y, x);
y -= a/b*x;
return r;
}
int Inv(int a, int n)
{
int r, x, y;
r = exgcd(a, n, x, y);
return r==1?(x+n)%n:-1;
}
ii、费马小定理求逆元
费马小定理为:当模数 为质数时,存在
由于 可以写作 ,那么存在 ,所以 就是 在模 意义下的逆元。
由此可得,
利用快速幂快速求解 。
long long ksm(long long a, long long k)
{
long long ans = 1;
while (k)
{
if (k&1)
ans = (ans * a) %mod;
a = (a * a) %mod;
k >>= 1;
}
return ans;
}
long long Inv(long long a)
{
return ksm(a, p-2);
}
iii、欧拉定理求逆元
在欧拉定理中,对于任意模数 ,有
其中 为欧拉函数:对正整数 ,欧拉函数是小于或等于 的正整数中与 互质的数的数目。
由此可得,对于任意模数,
iv、线性求逆元
设模数 ,则有 。
所以 。
我们将方程两边同乘以 得到 。
因为有 ,所以
为防止出现负数,写为
int Inv(int p)
{
inv[1] = 1;
for (int i = 1; i <= n; ++ i)
{
inv[i] = ((p - i/p)*inv[p % i]) %p;
}
}
3、逆元与组合数
因为求组合数 的过程中,可能涉及取模的运算,所以组合数就和逆元扯上了联系。
v、阶乘逆元(线性)
在组合数中,
设 ,由此我们将 可以得到 ,我们可以解决快速地将 的阶乘求出来、
那么对 就是要求其的逆元(通常 为素数),可以用上述 的方法求出。
又因为 ,所以可以快速的求出 组合数问题。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效