快速幂
快速幂
闲扯
本蒟蒻数学不好(• ̀ω•́ )✧,想写一篇快速幂的题解让自己对其的了解更加深入。
算法
题面
题目描述
给你三个整数\(b, p, k\)求 \(b ^ p \mod k\)
输入格式
输入只有一行三个整数,分别代表\(b, p, k\)
输出格式
输出一行一个字符串\(b ^ p \mod k = s\) ,其中\(b, p, k\)分别为题目给定的值,\(s\)为运算结果。
算法
我们在进行幂运算的时候将\(a\)自乘一次得到\(a ^ 2\),再把\(a ^ 2\)自乘一次变为\(a ^ 4\),接下来\(a ^ 8\)……,自乘\(n\)次后就变为了\(a ^ {2n}\),幂运算还有这样的一种原理\(a ^ xa ^ y = a^{x + y}\)。最重要的是下一点,我们要求出的是\(a ^ b\),在这里我们将\(b\)转化成二进制看一下,假设\(b = (39)_10\)等同于\(b = (100111)_2\),这些\(1\)分别代表十进制中的\(32, 4, 2, 1\),那么\(a ^ {39} = a ^ {32} \times a ^ 4 \times a ^ 2 \times a ^ 1\)。这样来表示的话我们就可以大大降低时间复杂度到\(O(log_2n)\)。
那么代码应该如何实现呢?首先我们定义一个初始值\(base = a\)和\(ans = 1\)来记录结果。我们通过一个\(while(b > 0)\)的循环来进行计算,我们的想法是当\(b\)在二进制表示下的第\(i\)位如果为\(1\)那么的话\(ans *= base;\)如果为\(0\)的话则继续,同时无论哪种情况都要\(base *= 2\)使他自己变成平方,这时我们就需要用到一种神奇的方法来判断第\(i\)位到第是什么表示为\(if(b\) & \(i)\),&为按位与的意思,即为当两者都是\(1\)的时候才会返回\(1\)否则返回\(0\),非常的巧妙;同时\(b >>= 1\)这个意思是\(b\)在二进制的表示下向右移一位,\((100111)_2 <<= (10011)_2\)这样进行操作直到\(b\)变为\(0\)。同时注意需要在每一步进行的同时\(/mod k\),这样才不会使答案溢出。
代码实现
#include<bits/stdc++.h>
using namespace std;
long long b,q,k;
long long quickpower(long long a,long long b){
long long ans=1,base=a;
while(b > 0){
if(b & 1) ans=ans*base%k;
base=base*base%k;
b >>=1;
}
return ans;
}
int main(){
cin>>b>>q>>k;
int ans=quickpower(b,q);
printf("%lld^%lld mod %lld=%lld",b,q,k,ans%k);
return 0;
}
完结撒花ヾ(✿゚▽゚)ノ