快速幂

快速幂

闲扯

本蒟蒻数学不好(• ̀ω•́ )✧,想写一篇快速幂的题解让自己对其的了解更加深入。

算法

题面

洛谷P1226快速幂

题目描述

给你三个整数\(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;
}

完结撒花ヾ(✿゚▽゚)ノ

posted @ 2020-11-16 20:31  summitsoul  阅读(190)  评论(0编辑  收藏  举报