【数论】快速幂

快速幂

给定 n 组 a i a_i ai, b i b_i bi, p i p_i pi,对于每组数据,求出 a i b i m o d {a_i}^{b_i} mod aibimod p i p_i pi 的值。

输入格式

第一行包含整数 n。

接下来 n 行,每行包含三个整数 a i a_i ai, b i b_i bi, p i p_i pi。

输出格式

对于每组数据,输出一个结果,表示 a i b i m o d {a_i}^{b_i} mod aibimod p i p_i pi的值。

每个结果占一行。

数据范围

1≤n≤100000,

1≤ a i a_i ai, b i b_i bi, p i p_i pi≤2× 1 0 9 10^9 109

输入样例:
复制代码
2
3 2 5
4 3 9
输出样例:
复制代码
4
1

【思路分析】

如果使用朴素算法要进行b次乘积运算,因此朴素算法的时间复杂度是O(b)的

但是使用快速幂算法即可将时间复杂度优化为logb的

快速幂的思路如下

对于一个数 a b a^b ab 我们可以先将

a 2 0 a ^{2^0} a20 mod p

a 2 1 a ^{2^1} a21 mod p

a 2 2 a ^{2^2} a22 mod p

...

a 2 l o g b a ^{2^{logb}} a2logb mod p

预处理出来

而且可以发现 a i a^{i} ai = a i − 1 a^{i - 1} ai−1 * a i − 1 a^{i - 1} ai−1 mod p

然后 a b a^b ab 就可以用预处理出来的数来表示

例如b的二进制是101101

则 a 45 a^{45} a45 = a 2 0 a ^{2^0} a20 * a 2 2 a ^{2^2} a22 * a 2 3 a ^{2^3} a23 * a 2 5 a ^{2^5} a25

代码如下

java 复制代码
import java.io.*;
import java.util.*;
public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter pw = new PrintWriter(System.out);
        int n = Integer.parseInt(br.readLine());
        while(n-- > 0) {
            String[] data = br.readLine().split(" ");
            int a = Integer.parseInt(data[0]);
            int b = Integer.parseInt(data[1]);
            int p = Integer.parseInt(data[2]);
            pw.println(function((long)a, b, p));
        }
        br.close();
        pw.close();
    }
    //求快速幂 a^b % p
    public static long function(long a, int b, int p) {
        long res = 1 % p;
        while(b > 0) {
            //如果b的末位是1
            if((b & 1) == 1) {
                res = res * a % p;
            }
            //a的计算可以通过上一次的a求出
            a = a * a % p;
            //b右移一位
            b >>= 1;
        }
        return res;
    }
}

快速幂的应用:求逆元

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

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

乘法逆元的定义

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

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

输入格式

第一行包含整数 n。

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

输出格式

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

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

数据范围

1≤n≤ 1 0 5 10^5 105,

1≤ a i a_i ai, p i p_i pi≤2∗ 1 0 9 10^9 109

输入样例:
复制代码
3
4 3
8 5
6 3
输出样例:
复制代码
1
2
impossible
费马小定理(可以通过欧拉函数推出)

费马小定理表述为:若 p 是质数,且整数 a 与 p 互质(即 gcd(a,p)=1,gcd表示最大公约数 ),那么有 a p − 1 a ^ {p - 1} ap−1 ≡ 1 (mod p) 。

推导乘法逆元公式

已知乘法逆元的定义:对于整数 a 和质数 p ,若存在整数 x ,使得 ax ≡ 1 (mod p) ,则 x 是 a 模 p 的乘法逆元。 由费马小定理 a p − 1 a ^ {p - 1} ap−1 ≡ 1 (mod p) ,等式两边同时除以 a (因为 a 与 p 互质,所以可以除 ),得到 a p − 2 a ^ {p - 2} ap−2 ≡ 1 a \frac{1}{a} a1 (mod p) 。 也就是说,当 p 是质数且 a 与 p 互质时,a 模 p 的乘法逆元就是 a p − 2 a^{p - 2} ap−2 mod p。

java 复制代码
import java.io.*;
import java.util.*;
public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter pw = new PrintWriter(System.out);
        int n = Integer.parseInt(br.readLine());
        while(n-- > 0) {
            String[] data = br.readLine().split(" ");
            int a = Integer.parseInt(data[0]);
            int p = Integer.parseInt(data[1]);
            //如果a是p的倍数,则一定没有逆元
            if(a % p == 0) {
                pw.println("impossible");
            } else {
                pw.println(function((long)a, p - 2, p));
            }
        }
        br.close();
        pw.close();
    }
    //求快速幂 a^b % p
    public static long function(long a, int b, int p) {
        long res = 1 % p;
        while(b > 0) {
            if((b & 1) == 1) {
                res = res * a % p;
            }
            a = a * a % p;
            b >>= 1;
        }
        return res;
    }
}
相关推荐
Wang's Blog26 分钟前
Java 接入Redis: 通用命令与键管理
java·服务器·redis
Wang's Blog28 分钟前
Java 接入Redis: 列表集合与有序集合操作命令
java·服务器·redis
Ivanqhz1 小时前
SVD++算法
java·服务器·网络·深度学习·神经网络
qq_2518364572 小时前
springboot vue3 开发实现 拼豆管理系统
java·开发语言·ai编程
caoerzhong2 小时前
JeeWMS 开源仓库管理系统全景解读:一套 Java WMS 如何把 WMS/OMS/BMS/TMS 装进同一个系统
java·开源
曹牧2 小时前
Java集合框架:List、ArrayList、Map 和 HashMap
java
顾城猿2 小时前
STOMP 协议
java
+VX:Fegn08953 小时前
计算机毕业设计|基于springboot + vue旅游管理系统(源码+数据库+文档)
java·开发语言·vue.js·spring boot·课程设计
需要8263 小时前
MySQL 索引 B+ 树与“查询为什么变慢了
java·spring boot·spring·spring cloud·tomcat
一 乐3 小时前
二手交易平台|基于springboot + vue二手交易平台(源码+数据库+文档)
java·数据库·vue.js·spring boot·小程序