數的快速冪與矩陣的快速冪
阿新 • • 發佈:2019-01-25
快速冪
對於任意底數的冪結果都可以分解為指數為2的冪的結果相乘。
因為任意一個數可以用二進位制來表示,所以我們的指數(假設為b),可以寫成
(其中,各子項的係數為0或1,因為二進位制)所以我們的
比如3^6 = 3^4*3^2
所以我們可以利用以上的結論,思想分解我們的指數為2的冪的多項式的形式,然後依次從低位考察這個多項式,若二進位制某一位為0,則該子項為0,那麼以該子項為冪的結果就為1,所以我們跳過該位。我們還發現式子2的每一個項都是前一項的平方,所以我們在考察指數多項式的每一位時,不管該位是不是0,都應該記錄該子項的結果,方便遇到二進位制為1時直接累乘該值即可,減少相乘次數。具體演算法如下:
/**
* 快速冪
* @param num 底數
* @param n 指數
* @return
*/
public static int fastPower(int num, int n){
int result = 1;
int digit = num;
while(n != 0){
if((n & 1) == 1){ //該數位為1, 意思分解為冪相乘時,有該數
result *= digit;
}
n >>= 1 ;
digit *= digit; //指數每右移一位,指數相當於乘以2,對應到冪結果應執行一次平方
}
return result;
}
複雜度分析
普通求冪需要連乘n次,所以複雜度為O(n)。而採用快速冪,把數的相乘按照指數二進位制形式的合併了,且合併規模的為上一次的二倍。比如求2的9次方,正常需要連乘9次,而採用快速冪可以降為6次。9的二進位制為4位,故需要4次乘法記錄當前中間值(該中間值主要為了減少乘法次數,方便遇到二進位制為1使用該值),外加2次的二進位制為1時需要乘以中間值。因為問題規模為自底向上倍增上去,故複雜度為O(logn)。
矩陣的快速冪
因為矩陣相乘滿足結合率,所以,我們可以擴充套件到二維陣列上,也就是求矩陣的冪。而且矩陣的快速冪原理與數的快速冪是一致的,都是利用指數的二進位制表現形式,不同的是我們需額外實現矩陣相乘演算法。
/**
* 矩陣快速冪
* @param base
* @param index
* @return
*/
public static int[][] fastPowMatrix(int[][] base, int index) {
int[][] res = new int[base.length][base[0].length];
for(int i = 0; i < base.length; i++) {
res[i][i] = 1;
}
int[][] t = base;
while(index != 0) {
if((index & 1) == 1) {
res = multipleMatix(res, t);
}
t = multipleMatix(t, t);
index >>= 1;
}
return res;
}
/**
* 矩陣相乘
* @param left
* @param right
* @return
*/
public static int[][] multipleMatix(int[][] left, int[][] right) {
int[][] res = new int[left.length][left[0].length];
for(int i = 0; i < left.length; i++) {
for(int j = 0; j < right.length; j++) {
for(int k = 0; k < left[0].length; k++) {
res[i][j] += left[i][k] * right[k][j];
}
}
}
return res;
}