逆元

求除法取模(a/b)%c要用到逆元即 (a/b)%c=a*(b关于模c的逆)%c

逆元类似于实数运算中的倒数,因为乘法是可以直接取模的,所以我们可以将除法转换成乘法,用a乘b的倒数即a乘b的逆元然后去取模就可以了。

逆元怎么求呢?

(a和p互质,a才有关于p的逆元)

1:根据费马小定理,我们可得出当p是素数时,对任意x,都有x^(p)≡  x(modp),

若x无法被p整除,那么x^(p-1)≡  1(modp),

那么可得出当模数p为素数x^(p-2)就是x的逆元。

const int mod = 1000000009;  
long long quickpow(long long a, long long b) {  
    if (b < 0) return 0;  
    long long ret = 1;  
    a %= mod;  
    while(b) {  
        if (b & 1) ret = (ret * a) % mod;  
        b >>= 1;  
        a = (a * a) % mod;  
    }  
    return ret;  
}  
long long inv(long long a) {  
    return quickpow(a, mod - 2);  
}  

2:扩展欧几里德算法

a*x + b*y = 1

如果ab互质,有解。

那么两边同时modp

ax%p1%p那么ax1(modp)

x就是a关于b的逆元

#include<cstdio>
typedef long long LL;
void ex_gcd(LL a, LL b, LL &x, LL &y, LL &d){
    if (!b) {d = a, x = 1, y = 0;}
    else{
        ex_gcd(b, a % b, y, x, d);
        y -= x * (a / b);
    }
}
LL inv(LL t, LL p){//如果不存在,返回-1 
    LL d, x, y;
    ex_gcd(t, p, x, y, d);
    return d == 1 ? (x % p + p) % p : -1;
}
int main(){
    LL a, p;
    while(~scanf("%lld%lld", &a, &p)){
        printf("%lld\n", inv(a, p));
    }
}

3:逆元线性筛法

用来求1,2,3....n关于p的逆元,复杂度O(n)

const int mod = 1000000009;  
const int maxn = 10005;  
int inv[maxn];  
inv[1] = 1;  
for(int i = 2; i < 10000; i++)  
    inv[i] = inv[mod % i] * (mod - mod / i) % mod;  



(忘了说, a和p互质,a才有关于p的逆元)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值