快速幂(求解原理+例题)

目录

反复平方法(快速幂):

代码: 

例题:快速幂求逆元


作用:

        快速求出 a^k \ mod \ p 的结果。

时间复杂度:

        O(logk)

        如果使用一般做法,从1循环到k,时间复杂度是O(k)

 

反复平方法(快速幂):

        将 k 用二进制表示:(k)_{10}=(....)_2

        那么  k = 2^{x_1}+2^{x_2} + ... +2^{x_t}\ \ \ x_t<=log_2k

        因此  a^k \ =\ a^{2^{x_1}+2^{x_2}+...+2^{x_t}} \ \ \ x_t<=log_2k

        我们可以把 a^k 拆分成  a^k \ =\ a^{2^{x_1}} * a^{2^{x_2}} *... * a^{2^{x_t}} \ \ \ x_t<=log_2k 

        因此我们只需要预处理出下面的,就可以解决上述方法:

         a^{2^0} \ mod \ p\\a^{2^1} \ mod\ p\\a^{2^2}\ mod\ p\\.\\.\\a^{2^{logk}}\ mod \ p

        如何求解这些需要预处理:

        每次乘2

        

qmi(long a,long k,long p){
    long res = 1;
    while(k!=0){
        if((k&1)==1) res = res*a%p; // 如果该位是1
        k = k>>1; // 右移一位
        a = a*a%p; //每次乘2
    }
    System.out.println(res);
}

         该代码使用了一种位运算技巧。

        位运算---求n的二进制表示中第k位是1还是0 (lowbit)-CSDN博客

例子:

 

 

标准例题代码: 

给定 n 组 ai,bi,pi,对于每组数据,求出 a_i^{b_i}\ mod\ p_i 的值。

输入格式

第一行包含整数 n。

接下来 n 行,每行包含三个整数 ai,bi,pi。

输出格式

对于每组数据,输出一个结果,表示 a_i^{b_i}\ mod\ p_i 的值。

每个结果占一行。

数据范围

1≤n≤100000,
1≤ai,bi,pi≤2×10^9

输入样例:

2
3 2 5
4 3 9

输出样例:

4
1

import java.util.*;
import java.io.*;

class Main{
    static final int N = 100010;
    static int n;
    public static void main(String[] args) throws IOException{
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        n = Integer.parseInt(in.readLine());
        while(n-->0){
            String[] s = in.readLine().split(" ");
            long a = Long.parseLong(s[0]);
            long b = Long.parseLong(s[1]);
            long p = Long.parseLong(s[2]);
            qmi(a,b,p); // 快速幂
        }
    }
    public static void qmi(long a,long b,long p){
        long res = 1;
        while(b!=0){
            if((b&1)==1) res = res*a%p; // 如果该位是1
            b = b>>1; // 右移一位
            a = a*a%p; //每次乘2
        }
        System.out.println(res);
    }
}

例题:快速幂求逆元

        费马定理。

给定 n 组 ai,pi,其中 pi 是质数,求 ai 模 pi 的乘法逆元,若逆元不存在则输出 impossible

注意:请返回在 0∼p−1 之间的逆元。

乘法逆元的定义

若整数 b,m 互质,并且对于任意的整数 a,如果满足 b|a,则存在一个整数 x,使得 \frac{a}{b}\equiv a*x\ (mod \ m),则称 x 为 b 的模 m 乘法逆元,记为 b^{-1}\ (mod\ m)

b 存在乘法逆元的充要条件是 b 与模数 m 互质。当模数 m 为质数时,b^{m-2} 即为 b 的乘法逆元。

输入格式

第一行包含整数 n。

接下来 n 行,每行包含一个数组 ai,pi,数据保证 pi 是质数。

输出格式

输出共 n 行,每组数据输出一个结果,每个结果占一行。

若 ai 模 pi 的乘法逆元存在,则输出一个整数,表示逆元,否则输出 impossible

数据范围

1≤n≤10^5,
1≤ai,pi≤2∗10^9

输入样例:

3
4 3
8 5
6 3

输出样例:

1
2
impossible

解决方法:

         \frac{a}{b}\equiv a*x\ (mod \ m)

       由题意可知: \frac{a}{b}\equiv a*b^{-1}\ (mod \ m)

        {a}\equiv a*b*b^{-1}\ (mod \ m)

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

        x 为 b 的模 m 乘法逆元,记为 b^{-1}\ (mod\ m),因此 b*x\equiv 1\ (mod \ m)

        由费马定理可知:

                ​​​​​​​        ​​​​​​​        b^{p-1}\ \equiv \ 1\ (mod\ p)\\b*b^{p-2} \ \equiv \ 1\ (mod\ p)

        因此,x = b^{p-2}\ (mod \ p)

        再使用快速幂解决:

import java.util.*;
import java.io.*;
class Main{
    static int n;
    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        n = Integer.parseInt(br.readLine());
        while(n-->0){
            String[] s = br.readLine().split(" ");
            int a = Integer.parseInt(s[0]);
            int p = Integer.parseInt(s[1]);
            long res = qmi(a,p-2,p);
            if(a%p==0) System.out.println("impossible");
            else System.out.println(res);
        }
    }
    public static long qmi(int a,int k,int p){
        long res = 1;
        while(k!=0){
            if((k&1)==1) res = res*a%p;
            k = k>>1;
            a = (int)((long)a*a%p);
        }
        return res;
    }
}

  • 22
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值