最初接触快速幂是在高中集训的时候,当时死活看不懂,现在重拾起来才发现异常简单。
众所周知,如果计算机要得到的结果,最基本的想法是进行n-1次乘法,但这样无疑是对时间资源的巨大浪费,转念一想,我们可以通过不断分解的方法进行求解。
比如,我们可以拆分为,这样乘法次数就变为两次。可那么为什么要这么拆分呢,我们可以注意到拆分后的指数都是2的不同次幂,对应指数11的二进制表示1011,因此我们要记住的原理是,任何一个整数的次幂都可以根据它的二进制表示拆分为形如上文的乘积表示。
我们假定初始系数base为底数自身,初始答案ans为1,随后将指数转换为二进制形式,每次取其最后一位,若为1,则ans应该乘上目前的系数,随后将系数自乘得到下一次的系数;若为0,则无需乘系数,只需要将系数自乘。
public int QuickPow(int base, int power) {
int ans = 1;
while (power != 0) {
if ((power & 1) == 1) {//power&1 其实就是得到power二进制表示下的最后一位
ans *= base;
}
base *= base;
power = power >> 1;
//power>>1 实现的操作是power左移一位,实际表现为丢弃二进制的最后一位
}
return ans;
}
矩阵快速幂与普通快速幂的区别在于
数的相乘--->矩阵相乘
初始值为1-->初始值为单位矩阵
因此只要了解如何进行矩阵乘法就可以将普通的快速幂转换为矩阵快速幂
矩阵乘法(不会的可自行百度)
矩阵快速幂代码如下(以二阶矩阵为例)
public int[][] pow(int[][] base, int power) {
int[][] res = {{1, 0}, {0, 1}};//单位矩阵
while (power > 0) {
if ((power & 1) == 1) {//若power二进制格式的最后一位为1 表明需要这一位,则将目前结果与base相乘
res = multiply(res, base);
}
power >>= 1;//舍弃二进制格式下的最后一位
base = multiply(base, base);//base自乘
}
return res;
}
public int[][] multiply(int[][] a, int[][] b) {//矩阵乘法
int[][] c = new int[2][2];
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j];
}
}
return c;
}
Over!欢迎提问和指正!!!