新手做的小小总结。
概念
快速幂是在进行大数计算时,为提高运算速率一个幂式取模(余)的运算。
举个栗子:(这里拿2举例了,其他数也一样)
幂为偶数:
2^16
=4(2^2)^8
=16(4^2)^4
=256(16^2)^2
幂为奇数:
(偶数的已经有思路了,那么就把奇转化成偶,这样就要分出来一个1,15=14+1,因此还需要用一个变量来记录它,这里我用一个变量cnt)
2^15
==>2^14 cnt=1*2=2;//拿出来一个2
==>4^7 cnt=2;
(这里没有再拿出来1了,不过现在又变成奇了,下次就要拿了)
==>4^6 cnt=2*4=8;
(此时拿出来的是一个4(7=6+1),另外cnt只是把它们分开计算,因此都还是乘的关系)
==>16^3 cnt=8;
==>16^2 cnt=8*16=128;
==>256^1 cnt=128;
结果:2^15=256*128;
总结:
对于一般的大数a^b。当b为偶数时,a^b可以转为a^2的b/2次方。当b为奇数时,a^b可以转为a^2的b/2次方,再乘以a。而a^2的b/2次方,以可以使用上述方式转为a^4的b/4次方再乘以某个数。
例题:
P1226 【模板】快速幂||取余运算
题目描述
输入b,p,k的值,求b^p mod k的值。其中b,p,k*k为长整型数。
输入输出格式
输入格式:
三个整数b,p,k.
输出格式:
输出“b^p mod k=s”
s为运算结果
输入输出样例
输入样例#1:
2 10 9
输出样例#1:
2^10 mod 9=7
我的代码:
#include <iostream>
#define ll long long
using namespace std;
ll f(ll x,ll y,ll k)
{
ll ans=1; //累积初始设为1;累加初始设为0。
while(y)
{
if(y&1) ans=(ans*x)%k; //注意不能写成ans*=x%k;下同不能。不懂的可以了解一下取模运算。
y>>=1; x=(x*x)%k; //y>>=1;是位运算,不要忘了“=”,同样也可以写成y/=2。
}
return ans;
}
int main()
{
ll b,p,k;
cin>>b>>p>>k;
cout<<b<<"^"<<p<<" mod "<<k<<"="<<f(b,p,k)%k;
return 0;
}
对于快速幂里的取模问题可以看看别人写的博客
https://blog.csdn.net/java_c_android/article/details/55802041
可练习的题目:
NYoj88 汉诺塔(一)
http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=88
另有矩阵快速幂:
P3390 【模板】矩阵快速幂
https://www.luogu.org/problemnew/show/P3390
参考:
快速幂及其简单应用
https://blog.csdn.net/usth_prophet/article/details/54961401