【洛谷 P1226】【模板】快速幂 题解(数学+递归+快速幂)

184 阅读1分钟

【模板】快速幂

题目描述

给你三个整数 a,b,pa,b,p,求 abmodpa^b \bmod p

输入格式

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

输出格式

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

样例 #1

样例输入 #1

2 10 9

样例输出 #1

2^10 mod 9=7

提示

样例解释

210=10242^{10} = 10241024mod9=71024 \bmod 9 = 7

数据规模与约定

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


思路

快速幂算法的主要思想是将指数bb进行分解,然后利用乘法的分配性质和取模的性质,将原问题转化为多个子问题的求解,从而大大提高了计算效率。

如果bb是偶数,那么abmodp=(ab/2modp)2modpa^b \mod p = (a^{b/2} \mod p)^2 \mod p;如果bb是奇数,那么abmodp=(ab1modp)×amodpa^b \mod p = (a^{b-1} \mod p) \times a \mod p。这样,我们就可以将原问题不断分解为规模更小的子问题,直到bb等于0,此时a0a^0等于1。

在计算大数的乘方时,结果往往会非常大,导致溢出。为了避免这种情况,在每一步计算中都取模。


AC代码

#include <iostream>
#define ll long long
#define AUTHOR "HEX9CF"
using namespace std;

ll qpow(int a, int b, int p) {
	if (!b) {
		return 1;
	}
	if (b % 2 == 1) {
		return (qpow(a, b - 1, p) * a) % p;
	} else {
		ll tmp = qpow(a, b >> 1, p) % p;
		return (tmp * tmp) % p;
	}
	return 0;
}

int main() {
	int a, b, p;
	cin >> a >> b >> p;
	ll ans = qpow(a, b, p);
	printf("%d^%d mod %d=%lld", a, b, p, ans);
	return 0;
}