费马小定理,快速幂求解,欧几里得算法

一.费马小定理+快速幂求解+ 欧几里得算法求逆元或扩展欧几里得求逆元

1.费马小定理

若存在整数 a , p 且gcd(a,p)=1,即二者互为质数,则有a^(p-1)≡ 1(mod p)。(这里的 ≡ 指的是左右两边的数对p求模结果相同。a^(p-1)≡ 1(mod p)是指a的p-1次幂取模与1取模恒等)

2.逆元

逆元的用处:

(a + b) % p = (a%p + b%p) %p (对)

(a - b) % p = (a%p - b%p) %p (对)

(a * b) % p = (a%p * b%p) %p (对)

(a / b) % p = (a%p / b%p) %p (错)

eg:(100/50)%20 = 2 ≠ (100%20) / (50%20) %20 = 0

对于一些题目,我们必须在中间过程中进行求余,否则数字太大,电脑存不下,那如果这个算式中出现除法,我们是不是对这个算式就无法计算了呢?

这时就需要逆元了!!!  !

定义:

现在有:a*x ≡ 1 (mod p),x叫做a关于p的逆元。

eg:2 * 3 % 5 = 1,那么3就是2关于5的逆元,或者说2和3关于5互为逆元。

a的逆元,我们用inv(a)来表示

那么(a  /  b) % p = (a * inv(b) ) % p = (a % p * inv(b) % p) % p   这样就把除法,完全转换为乘法。

3.快速幂

求 a^k mod p,时间复杂度 O(logk)

int qmi(int a, int k, int p)  // 求a^k mod p
{
    int res = 1;
    while (k)
    {
        if (k & 1) res = (LL)res * a % p;
        a = (LL)a * a % p;
        k >>= 1;
    }
    return res;
}

4.欧几里得算法

也叫辗转相除法这是小学二年级都会滴

int gcd(int a, int b)  // 欧几里得算法
{
    return b ? gcd(b, a % b) : a;
}

 那我们顺便再说一下

lcm = a/gad(a,b)*b 
gcd(ka, kb) = k * gcd(a, b)
lcm(ka, kb) = k * lcm(a, b)
lcm(S/a, S/b) = S/gcd(a, b)

4.求解

a^(p-1) ≡1 (mod p)

两边同除以a

a^(p-2) ≡ inv(a) (mod p)

所以inv(a) = a^(p-2) (mod p)  且  gcd(a,p)==1

综合上述算法就变得非常简单啦

上代码

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;


int gcd(int a, int b)  // 欧几里得算法
{
    return b ? gcd(b, a % b) : a;
}

int qmi(int a,int k,int p)  //快速幂
{
    int res = 1;
    while(k)
    {
        if(k&1) res = (LL) res * a % p;
        a = (LL)a * a % p;
        k >>= 1;    
    }
    return res;
}
int main()
{
    int n;
    cin >> n;
    while(n--)
    {
        int a,p;
        cin >> a >> p;
        if(gcd(a,p) != 1) puts("impossible");
        else
            cout << qmi(a,p-2,p) << endl;
    }
    return 0;
}

5.扩展欧几里得算法( •̀∀•́ )

裴蜀定理:

定义:对于任意正整数a,b一定存在非零整数x,y使得ax+by = gcd(a, b) 。

当a与b互质时gcd(a,b)==1所以ax+by = 1 两边同时求余b

a*x % b + b*y % b = 1 % b

a*x % b = 1 % b

a*x = 1 (mod b)

所以x是a关于b的逆元

同理:y就是b关于a的逆元

算法代码

#include <iostream>
using namespace std;
typedef long long LL;

void ex_gcd(LL a, LL b, LL &d, LL &x, LL &y)
{
    if(!b)  x = 1 , y = 0 , d = a;
    else
    {
        ex_gcd(b , a%b , d , y , x);
        y -= a/b * x;
    }
}

int main()
{
    int n; 
    cin >> n;
    while(n --)
    {
        LL a,b,d,x,y;
        cin >> a >> b;
        ex_gcd(a,b,d,x,y);
        if(d==1)  cout << (x + b)%b << endl;
        else puts("impossible");
    }
    return 0;
}

又学会了一个新知识好开心(•̤̀ᵕ•̤́๑)ᵒᵏᵎᵎᵎᵎ 

二.中国剩余定理(孙子定理)

中国剩余定理给出了以下的一元线性同余方程组:

中国剩余定理说明:假设整数m1,m2, ... ,mn两两互质,则对任意的整数:a1,a2, ... ,an,

 方程组(S)

有解,并且通解可以用如下方式构造得到:

是整数m1,m2, ... ,mn的乘积,并设

是除了mi以外的n- 1个整数的乘积。

这个就是逆元了

通解形式为

在模M的意义下,方程组(S)只有一个解:

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值