标签:main amp space 特殊 题目 实用 表示 链接 mes
题目链接:https://www.luogu.org/problemnew/show/P1226
第一次学快速幂,将别人对快速幂原理的解释简要概括一下:
计算a^b时,直接乘的话计算次数为b,而快速幂则只需要log2(b)次,很实用。
快速幂有很多种解释,以下介绍两种:
一.
我们可以将b转换为二进制来看,比如计算2^11,因为(11)10=(1011)2,所以211=21*8+0*4+1*2+1*1=21×8×21×2×21×1。
具体计算可以参考代码:
int quickPower(int a, int b)//是求a的b次方 { int ans = 1, base = a;//ans为答案,base为a^(2^n) while(b > 0)//b是一个变化的二进制数,如果还没有用完 { if(b & 1)//&是位运算,b&1表示b在二进制下最后一位是不是1,如果是: ans *= base;//把ans乘上对应的a^(2^n) base *= base;//base自乘,由a^(2^n)变成a^(2^(n+1)) b >>= 1;//位运算,b右移一位,如101变成10(把最右边的1移掉了),10010变成1001。现在b在二进制下最后一位是刚刚的倒数第二位。结合上面b & 1食用更佳 } return ans; }
一般会将快速幂与取余运算结合在一起,例如本题。取余运算有一些很好的性质:
(a+b) mod c = (a mod c + b mod c) mod c
(a*b) mod c =((a mod c)*(b mod c)) mod c
即在本题中求幂的过程中取余和求幂之后取余是一样的。另外,关于本题,有一个特殊情况,即k=1时,结果总为0,需要特判(最后一个测试点)。
本题的AC代码如下:
#include<cstdio> using namespace std; long b,p,k,res=1; void QuickPower(long bb,long pp,long kk){ long base=bb; base%=kk; while(pp){ if(pp&1){ res*=base; res%=kk; } base*=base; base%=kk; pp>>=1; } } int main(){ scanf("%ld%ld%ld",&b,&p,&k); if(k!=1){ QuickPower(b,p,k); printf("%ld^%ld mod %ld=%ld\n",b,p,k,res); } else printf("%ld^%ld mod %ld=0\n",b,p,k); return 0; }
二.关于快速幂的另一种理解方式:
对于a^b,若b为偶数,递归计算(a2)b/2;若b为奇数,则递归计算a*(a2)(b-1)/2。
标签:main amp space 特殊 题目 实用 表示 链接 mes
原文地址:https://www.cnblogs.com/FrankChen831X/p/10327734.html