逆元
1 定义
如果一个线性同余方程
2 费马小定理:
3 拓展欧几里得:
void Exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) x = 1, y = 0;
else Exgcd(b, a % b, y, x), y -= a / b * x;
}
int main() {
ll x, y;
Exgcd (a, p, x, y);
x = (x % p + p) % p;
printf ("%d\n", x); //x是a在mod p下的逆元
}
4 线性递推求法:
int inv[1000000];
void find_inv(int last,int p)
//求1~last所有数模p意义下的逆元
{
inv[1]=1;//1的逆元就是1本身
for(int i=2;i<=last;i++)
inv[i]=(long long)(p-p/i)*(inv[p%i])%p;
//注意longlong,否则有可能导致溢出
}
5 线性求任意 n 个数的逆元
上面的方法只能求
首先计算
因为
同理我们可以依次计算出所有的
所以我们就在
s[0] = 1;
for (int i = 1; i <= n; ++i) s[i] = s[i - 1] * a[i] % p;
sv[n] = qpow(s[n], p - 2);
// 当然这里也可以用 exgcd 来求逆元,视个人喜好而定.
for (int i = n; i >= 1; --i) sv[i - 1] = sv[i] * a[i] % p;
for (int i = 1; i <= n; ++i) inv[i] = sv[i] * s[i - 1] % p;