2026/5/29 -P1226 【模板】快速幂

题面:

P1226 【模板】快速幂

题目描述

给你三个整数 \(a,b,p\),求 \(a^b \bmod p\)

输入格式

输入只有一行三个整数,分别代表 \(a,b,p\)

输出格式

输出一行一个字符串 a^b mod p=s,其中 \(a,b,p\) 分别为题目给定的值, \(s\) 为运算结果。

输入输出样例 #1

输入 #1

2 10 9

输出 #1

2^10 mod 9=7

说明/提示

样例解释

\(2^{10} = 1024\)\(1024 \bmod 9 = 7\)

数据规模与约定

对于 \(100\%\) 的数据,保证 \(0\le a,b < 2^{31}\)\(a+b>0\)\(2 \leq p \lt 2^{31}\)

首先观察数据范围:保证 \(0\le a,b < 2^{31}\)\(a+b>0\)\(2 \leq p \lt 2^{31}\),所以需要开long long
读题发现可以简单的先写一个循环暴力,时间复杂度\(O(b)\)得到60pts:

#include <iostream>
using namespace std;
int main() {
    long long a, b, p;
    cin >> a >> b >> p;
    long long res = 1; //用于存储当前累积的乘积对 p 取模后的结果
    for (long long i = 0; i < b; i++) {
        res = (res * a) % p;//由于a和b最大可接近2的31次方,无法存储,
        //所以需要边乘边取余,保证结果在long long范围之内。
    }
    //按要求输出
    cout << a << "^" << b << " mod " << p << "=" << res << endl;
    return 0;
}

如何优化呢?
考虑二进制优化。首先将指数b分解为二进制形式,如\(b=13=(1101)_2=8+4+0+1\),那么可以得到\(a^{13}=a^{8}·a^{4}·a^{0}·a^{1}\),那么如何快速获得\(a^{2^k}\)呢?可以通过反复平方:\(a^{2^0}=a\)\(a^{2^1}=a^2\)\(a^{2^2}=(a^2)^2\)......
以此类推可以得到规律:在遍历\(b\)的二进制位时,每次把当前底数平方,就能依次得到\(b^{2^0}\)\(b^{2^1}\)\(b^{2^2}\)......
处理溢出:因为最终要对\(p\)取模,根据运算性质\((x·y) \mod p=(x \mod p)·(y \mod p) \mod p\),可以在每次乘法和平方后立即取模,避免溢出。
具体步骤:

  • 初始化 ans = 1(累积结果)。
  • 初始化 x = a(当前底数,代表 (a{20}))。
  • y > 0 时循环:
    • y 的最低位为1(y & 1 为真),则 ans = (ans * x) % p
    • 然后 x = (x * x) % p(准备下一二进制位对应的值)。
    • 最后 y >>= 1(去掉最低位,继续处理更高位)。
  • 循环结束,ans 即为答案。

每循环一次,指数 y 右移一位,循环次数等于 b 的二进制位数,即 $\lfloor \log_2 b \rfloor + 1$,故时间复杂度为 \(O(\log b)\)
\(ACcode:\)

#include<bits/stdc++.h>  
#define int long long
using namespace std;
int a, b, p;              
int ksm(int x, int y) {
    int ans = 1;           // ans 初始化为 1,因为任何数的 0 次幂都是 1
    // 当指数 y 不为 0 时,继续循环
    while (y) {
        // 如果 y 的二进制最低位是 1(即 y 是奇数)
        if (y & 1) {
            // 将当前的底数 x 乘到答案 ans 上,并立即对 p 取模,防止溢出
            ans = (ans * x) % p;
        }
        // 底数平方(x = x^2),并取模,为下一位做准备
        x = (x * x) % p;
        // 指数右移一位(相当于整除 2),丢弃已经处理过的最低位
        y >>= 1;
    }
    // 返回最终计算结果
    return ans;
}
int main() {
    // 从标准输入读取三个整数:底数 a,指数 b,模数 p
    cin >> a >> b >> p;
    // 按照题目要求的格式输出:a^b mod p = 结果
    cout << a << "^" << b << " mod " << p << "=" << ksm(a, b);
    return 0;        
}
posted @ 2026-05-30 00:11  Enzo_Kevin  阅读(12)  评论(0)    收藏  举报