《算法竞赛进阶指南》0x01 位运算-1.a^b

AcWing 89. a^b

题目描述

求 a a a 的 b b b 次方对 p p p 取模的值。

输入格式

三个整数 a , b , p a,b,p a,b,p ,在同一行用空格隔开。

输出格式

输出一个整数,表示a^b mod p的值。

数据范围

0 ≤ a , b ≤ 10 9 0 \le a,b \le 10^9 0≤a,b≤109
1 ≤ p ≤ 10 9 1 \le p \le 10^9 1≤p≤109

输入样例:
复制代码
3 2 7
输出样例:
复制代码
2
解题思路

令 a = 2 a = 2 a=2, b = 34 b = 34 b=34:
2 34 = 2 ( 100010 ) B 2^{34} = 2^{(100010)B} 234=2(100010)B
= 2 2 5 ⋅ 1 + 2 4 ⋅ 0 + 2 3 ⋅ 0 + 2 2 ⋅ 0 + 2 1 ⋅ 1 + 2 0 ⋅ 0 = 2^{2^5·1+2^4·0+2^3·0+2^2·0+2^1·1+2^0·0} =225⋅1+24⋅0+23⋅0+22⋅0+21⋅1+20⋅0
= 2 2 5 ⋅ 1 + 2 1 ⋅ 1 = 2^{2^5·1+2^1·1} =225⋅1+21⋅1
= 2 2 5 ⋅ 1 ⋅ 2 2 1 ⋅ 1 = 2^{2^5·1}·2^{2^1·1} =225⋅1⋅221⋅1

  • 因为 2 2 n = 2 2 n − 1 ⋅ 2 2 n − 1 2^{2^n}=2^{2^n−1}·2^{2^n−1} 22n=22n−1⋅22n−1
  • 所以我们可以使用一个临时变量 t e m p temp temp 存储 2 2 i 2^{2^i} 22i,每移动一位, t e m p = t e m p 2 % p temp = temp^2 \% p temp=temp2%p,起到递增效果;
  • 如果该位对应的二进制位数为 1 1 1,
  • 则将该临时变量 t e m p temp temp 累乘至结果:
  • a n s = a n s ⋅ t e m p % p ans = ans·temp \% p ans=ans⋅temp%p。
  • 注意. t e m p temp temp 初始值为 a 2 0 a^{2^0} a20, a n s ans ans 初始值为 1 1 1。
参考代码
无注释
cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
long long a, b, p, temp, ans;

int main(){
	cin >> a >> b >> p;
    temp = a, ans = 1;
    for(; b; b >>= 1){
    	if(b & 1)	ans = ans * temp % p;
		temp = temp * temp % p;
	}
	cout << ans % p;
	return 0;
}
详细注释
cpp 复制代码
#include<bits/stdc++.h>   // 包含几乎所有标准库,方便竞赛使用
using namespace std;

long long a, b, p, temp, ans;   // 定义变量:a 底数,b 指数,p 模数,temp 记录当前权值,ans 记录结果

int main(){
    cin >> a >> b >> p;          // 读入三个整数
    temp = a;                    // temp 初始化为 a,表示 a 的 1 次方
    ans = 1;                     // ans 初始化为 1(任何数的 0 次方为 1,用于累乘)

    // 快速幂算法(二进制取模幂)
    // 循环将指数 b 按二进制位处理,直到 b 变为 0
    for(; b; b >>= 1){           // 每次循环将 b 右移一位,相当于 b //= 2
        if(b & 1)                // 如果当前最低位是 1,说明需要乘上当前权值
            ans = ans * temp % p;   // 将 ans 乘以当前权值并取模 p
        temp = temp * temp % p;  // 权值平方,即从 a^(2^k) 变为 a^(2^(k+1)),并取模 p
    }

    // 输出结果。由于循环中已经不断取模,ans 已经小于 p,但考虑 b=0 且 p=1 的情况,
    // 此时 ans 仍为 1,但 1 % 1 = 0,所以再取一次模保证正确性
    cout << ans % p;

    return 0;                    // 程序结束
}
相关推荐
wfbcg3 分钟前
每日算法练习:LeetCode 15. 三数之和 ✅
算法·leetcode·职场和发展
2301_822703209 分钟前
开源鸿蒙跨平台Flutter开发:跨端图形渲染引擎的类型边界与命名空间陷阱:以多维雷达图绘制中的 dart:ui 及 StrokeJoin 异常为例
算法·flutter·ui·开源·图形渲染·harmonyos·鸿蒙
y = xⁿ11 分钟前
【LeetCode Hot100】双指针:分离指针
算法·leetcode
学习永无止境@11 分钟前
Verilog中有符号数计算
图像处理·算法·fpga开发
6Hzlia15 分钟前
【Hot 100 刷题计划】 LeetCode 41. 缺失的第一个正数 | C++ 原地哈希题解
c++·leetcode·哈希算法
十五年专注C++开发19 分钟前
达梦数据库在Linux备份报错 -8003: 缺少本地或者远程归档 解决方案
数据库·c++·dm·备份复原
yy_xzz36 分钟前
【Linux开发】I/O 复用:select 模型
linux·c++·select
小肝一下43 分钟前
每日两道力扣,day6
数据结构·c++·算法·leetcode·双指针·hot100
ambition202421 小时前
【算法详解】飞机降落问题:DFS剪枝解决调度问题
c语言·数据结构·c++·算法·深度优先·图搜索算法