快速冪和矩陣快速冪(複雜度Olog(n))C++實現
阿新 • • 發佈:2018-12-24
快速冪
快速冪顧名思義,就是快速算某個數的多少次冪。其時間複雜度為 O(log₂N), 與樸素的O(N)相比效率有了極大的提高。
快速冪實現原理
快速冪的原理比較好懂,就是說假如我們求的是3^11
,其實比較通用的辦法就是
for 1:11
a*=3;
時間複雜度為O(n), 那麼我們有沒有更快的辦法呢? 有的~就是下面要說的快速冪。
快速冪就是把指數進行一次log(N)級別的變換。11 = 2^3+2^1+2^0
那麼我只需要算3^1
和3^2
還有3^8
這樣複雜度就降下來了。算3^1
需要一次記為a
,把a
平方就是3^2
記為b
,把b
平方就是3^4
記為c
,再平方就是3^8
記為d
,這樣把a
b d
快速冪程式碼
程式碼如下:
這個程式碼因為比較簡單,所以很容易懂,下面的矩陣快速冪是我自己寫的,可能會比較難~
int pow3(int a,int b)
{
int ans = 1,base = a;
while(b!=0)
{
if(b&1)
ans *= base;
base *= base;
b>>=1;
}
return ans;
}
矩陣快速冪
矩陣快速冪是個很好玩的東西~ 為啥捏? 因為它能在Olog(N)級別的時間求的第N個斐波納挈數列~叼不叼~(什麼?你不知道什麼是斐波納挈。請百度~1 1 2 3 5 8...數列)
實現原理
那是怎麼實現呢?首先我們設立ans矩陣{1, 1; 1, 0}.然後這個矩陣就是類似上面的3
這個底數,然後直接矩陣相乘就可以了。
斐波納挈數列是F(n) = F(n-1) + F(n-2)
,下面的程式碼是難一點的,F(n)
= a*F(n-1) + b*F(n-2)
這個數列的,F(1) = F(2) = 1.
實現程式碼
程式碼如下:
// // main.cpp // numberSequence_hdu // // Created by Alps on 14/12/22. // Copyright (c) 2014年 chen. All rights reserved. // #include <iostream> using namespace std; void multiMatrix(int ma[][2],int a, int b){ int i,j; int cp[2][2] = {0,0,0,0};; for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { cp[i][j] = ((ma[i][0]*ma[0][j])%7 + (ma[i][1]*ma[1][j])%7)%7; // printf("%d ",cp[i][j]); } // printf("\n"); } for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { ma[i][j] = cp[i][j]; } } } void multiDoubleMatrix(int cp[][2], int ma[][2], int a, int b){ int temp[2][2]; int i,j; for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { temp[i][j] = ((cp[i][0]*ma[0][j])%7 + (cp[i][1]*ma[1][j])%7)%7; } } for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { cp[i][j] = temp[i][j]; } } } int calculate(int ma[][2], int a, int b, int c){ if (c <= 0) { return 1; } int cp[2][2] = {1,0,0,1}; while (c) { if (c&1) { multiDoubleMatrix(cp, ma, a, b); } multiMatrix(ma, a, b); c = c>>1; } return (cp[0][0]+cp[0][1])%7; } int main(int argc, const char * argv[]) { int a,b,c; while (1) { scanf("%d %d %d",&a,&b,&c); int ma[][2] = {a%7,b%7,1,0}; // printf("%d %d %d %d\n",ma[0][0],ma[0][1],ma[1][0],ma[1][1]); if (a == 0 && b == 0 && c == 0) { break; } printf("%d\n",calculate(ma, a, b, c-2)); } return 0; }