乘法逆元
- 什么是乘法逆元
如果(ax equiv 1 pmod{p}),且(gcd(a,p)=1)((a)与(p)互质),则称(a)关于模(p)的乘法逆元为(x)。(感觉就是(a)的倒数) - 乘法逆元用来干什么
模运算符合以下分配律:
[(a+b) mod p = (a mod p + b mod p)mod p
]
[(a-b) mod p = (a mod p - b mod p)mod p
]
[(a*b) mod p = (a mod p + b mod p)mod p
]
[(a oplus b) mod p = ((a mod p) oplus b)mod p
]
但是取模运算不符合除法分配律,于是就要先求分母的倒数(不严谨,但是这里可以这么理解),然后再用乘法去算。
3. 如何求乘法逆元
结合费马小定理
[a^{p-1} equiv 1 pmod p
]
代入得
[ax equiv a^{p-1} pmod p
]
[x equiv a^{p-2} pmod p
]
然后用快速幂算一下就好
4. 没什么例题,但是要提一下洛谷P3811
这个题用快速幂去做,时间复杂度为(O(nlogn)),题目要求O(n),就要去推递推式:
我们知道
[1^{-1} equiv 1 pmod p
]
设(p = k * i + r),也就是(k)是(p/i)得商,(r)为余数。
在(mod p)的意义下
[k * i + r equiv 0 pmod p
]
然后乘上(r^{-1}),(i^{-1})后得
[i^{-1} equiv -k*r^{-1}pmod{p}
]
将(k)换掉((1 < r < i < p)):
[i^{-1} equiv lfloor frac{p}{i}
floor * (p mod i)^{-1} pmod{p}
]
然后就得到了(1 sim n)的逆元
#include<bits/stdc++.h>
using namespace std;
const int N = 3 * 1e6 + 10;
int f[N];
int n,p;
int main()
{
scanf("%d%d",&n,&p);
f[1] = 1;
puts("1");
for(int i = 2;i <= n;i ++ )
{
f[i] = (long long)(p - p / i) * f[p % i] % p;
printf("%d
",f[i]);
}
return 0;
}
下一个坑应该是拉格朗日插值(