逆元

1、思路

(1)当n为质数时,可以用快速幂求逆元:

a / b ≡ a * x (mod n)
两边同乘b可得 a ≡ a * b * x (mod n)
即 1 ≡ b * x (mod n)
同 b * x ≡ 1 (mod n)
由费马小定理可知,当n为质数时
b ^ (n - 1) ≡ 1 (mod n)
拆一个b出来可得 b * b ^ (n - 2) ≡ 1 (mod n)
故当n为质数时,b的乘法逆元 x = b ^ (n - 2)

(2)当n不是质数时,可以用扩展欧几里得算法求逆元:

a有逆元的充要条件是a与p互质,所以gcd(a, p) = 1
假设a的逆元为x,那么有a * x ≡ 1 (mod p)
等价:ax + py = 1
exgcd(a, p, x, y)

快速幂求逆元代码模板:

#include <iostream>

using namespace std;
typedef long long ll;

ll qmi(int a,int k,int p)
{
        ll res=1;
        while(k)
        {
        if(k&1)
            res=res*a%p;
        a=(ll)a*a%p;
        k>>=1;
    }
    return res;
}

int main()
{
    int n; 
    scanf("%d",&n);
    while(n --)
    {
        int a,p;
        scanf("%d %d",&a,&p);
        if(a%p==0) 
            puts("impossible");
        else 
            printf("%lld",qmi(a,p-2,p));
    }
    return 0;
}

扩展欧几里得算法求逆元代码模板:

#include <iostream>
using namespace std;
typedef long long ll;
int n;

int exgcd(int a,int b,int &x,int &y)
{
    if(!b)
    {
        x=1,y=0;
        return a;
    }
    int d=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return d;
}

int main()
{
    scanf("%d",&n);
    while(n--)
    {
        int a,p,x,y;
        // if (a < p) swap(a, p);
        scanf("%d %d",&a,&p);
        int d=exgcd(a,p,x,y);
        if(d == 1) 
            printf("%d",(ll)x+p)%p);//保证x是正数
        else 
            puts("impossible");
    }
    return 0;
}


























全部评论

相关推荐

就只能3个月,但是要求长期全职实习
Swaying:你确实是能长期实习啊,但是你那时候有事也没啥办法嘛
点赞 评论 收藏
分享
05-12 11:09
已编辑
门头沟学院 后端
已注销:没必要放这么多专业技能的描述。这些应该是默认已会的,写这么多行感觉在凑内容。项目这块感觉再包装包装吧,换个名字,虽然大家的项目基本都是网上套壳的,但是你这也太明显了。放一个业务项目,再放一个技术项目。技术项目,例如中间件的一些扩展和尝试。
点赞 评论 收藏
分享
04-27 18:53
江苏大学 Java
Offer急救室_IT校招版:1. 缺乏量化结果支撑 2. 项目太同质化查看图片
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务