Fork me on GitHub

快速幂

快速幂的用法及推导

之前算一个\(a^k\)时间复杂度是\(O(K)\).搞一个循环不断的相乘

现在是\(O(logk)\)

在30次之内算出来

核心思想:反复平方法

等号两边同时模一个数,那个大小是不变的

代码

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

LL qmi(int a, int n, int mod)
{
    LL res = 1 % p;  // 当 p = 1, b = 0的时候是有区别的  
    while(n)
    {
        if(n & 1)  res = res * a % mod;
        a = a * (LL) a % mod; // 低进制向高自动转换
        n >>= 1; 
    }
    return res;
}


int main()
{
    int n;
    cin >> n;
    while(n--)
    {
        int a, b, p;
        cin >> a >> b >> p;
        cout << quick_mod(a, b, p) << endl;
    }
    return 0;
}

快速幂求逆元

背景介绍以及定义

在很多时候我们都需要进行取余运算。加减乘都很容易取余

但是除法取余数是很麻烦的一件事情,所以我们就考虑把除法的求余转换成求乘法的余数

$ a/b \equiv a * x \pmod{m}$

则称\(x\)\(b\)\(mod m\)的乘逆元

逆元是一个整数只是一个标记

由逆元的推导式子可得:

$ b*b^{-1} \equiv 1 \pmod{m}$

若m又由费马小定理可知:

\(b^{m-1} \equiv 1 \pmod{m}\)

化简得

\(b*b^{m-2} \equiv 1 \pmod{m}\)

所以\(b^{-1}\)就等于\(b^{m-2}\)

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


LL qmi(int a, int b, int mod)
{
    LL res = 1 % mod;
    while(b)
    {
        if(b & 1) res = res * a % mod;
        a = (LL)a * a % mod;
        b >>= 1;
    }
    return res % mod;
}

int gcd(int a, int b)
{
    return b ? gcd(b, a%b) : a;
}


int main()
{
    int n;
    cin >> n;
    while(n--)
    {
        int a, p;
        cin >> a >> p;
        if(gcd(a, p) == 1)
        {
        cout << qmi(a, p - 2, p) << endl;
        }
        else cout << "impossible" << endl;
        
    }
    return 0;
}

题目中限定了 \(p\)一定是质数,所以如果 \(a\)\(p\) 有公因子,那么 \(a\) 就一定是 \(p\) 的倍数。

posted @ 2020-02-21 15:57  WalterJ726  阅读(96)  评论(0编辑  收藏  举报