快速矩陣快速冪

2021-06-16 16:36:04 字數 3080 閱讀 2987

出處:

矩陣的快速冪是用來高效地計算矩陣的高次方的。將樸素的o(n)的時間複雜度,降到log(n)。

這裡先對原理(主要運用了矩陣乘法的結合律)做下簡單形象的介紹:

一般乙個矩陣的n次方,我們會通過連乘n-1次來得到它的n次冪。

但做下簡單的改進就能減少連乘的次數,方法如下:

把n個矩陣進行兩兩分組,比如:a*a*a*a*a*a  =>  (a*a)*(a*a)*(a*a)

這樣變的好處是,你只需要計算一次a*a,然後將結果(a*a)連乘自己兩次就能得到a^6,即(a*a)^3=a^6。算一下發現這次一共乘了3次,少於原來的5次。

以上都是取乙個具體的數來作為最小單位的長度,這樣做雖然能夠改進效率,但缺陷也是很明顯的,取個極限的例子(可能有點不恰當,但基本能說明問題),當n無窮大的時候,你現在所取的長度其實和1沒什麼區別。所以就需要我們找到一種與n增長速度」相適應「的」單位長度「,那這個長度到底怎麼去取呢???這點是我們要思考的問題。

有了以上的知識,我們現在再來看看,到底怎麼迅速地求得矩陣的n次冪。

既然要減少重複計算,那麼就要充分利用現有的計算結果咯!~怎麼充分利用計算結果呢???這裡考慮二分的思想。。

計算機處理的是離散的資訊,都是以0,1來作為訊號的處理的。可想而知二進位制在計算機上起著舉足輕重的地位。它能將模擬訊號轉化成數碼訊號,將原來連續的實際模型,用乙個離散的演算法模型來解決。  好了,扯得有點多了,不過相信這寫對下面的講解還是有用的。

回頭看看矩陣的快速冪問題,我們是不是也能把它離散化呢?比如a^19  =>  (a^16)*(a^2)*(a^1),顯然採取這樣的方式計算時因子數將是log(n)級別的(原來的因子數是n),不僅這樣,因子間也是存在某種聯絡的,比如a^4能通過(a^2)*(a^2)得到,a^8又能通過(a^4)*(a^4)得到,這點也充分利用了現有的結果作為有利條件。下面舉個例子進行說明:

現在要求a^156,而156(10)=10011100(2) 

也就有a^156=>(a^4)*(a^8)*(a^16)*(a^128)  考慮到因子間的聯絡,我們從二進位制10011100中的最右端開始計算到最左端。細節就說到這,下面給核心**:

while(n)

裡面的乘號,是矩陣乘的運算,res是結果矩陣。

第3行**每進行一次,二進位制數就少了最後面的乙個1。二進位制數有多少個1就第3行**就執行多少次。

好吧,矩陣快速冪的講解就到這裡吧。在文章我最後給出我實現快速冪的具體**(**以3*3的矩陣為例)。

現在我就說下我對二進位制的感想吧:

我們在做很多」連續「的問題的時候都會用到二進位制將他們離散簡化

1.多重揹包問題

2.樹狀陣列

3.狀態壓縮dp

……………還有很多。。。究其根本還是那句話:化連續為離散。。很多時候我們並不是為了解決乙個問題而使用二進位制,更多是時候是為了優化而使用它。所以如果你想讓你的程式更加能適應大資料的情況,那麼學習學習二進位制及其演算法思想將會對你有很大幫助。

#include #include #include #include using namespace std;

int n;

struct matrix

origin,res;

matrix multiply(matrix x,matrix y)}}

return temp;

}void init()

printf("\n");

}printf("\n");

memset(res.a,0,sizeof(res.a));

res.a[0][0]=res.a[1][1]=res.a[2][2]=1; //將res.a初始化為單位矩陣

}void calc(int n)

printf("%d次冪結果如下:\n",n);

for(int i=0;i<3;i++)

printf("\n");

}int main()

return 0;

}

nyoj_301遞推求值

時間限制:

1000 ms  |  記憶體限制:

65535 kb

難度: 4

描述

給你乙個遞推公式:

f(x)=a*f(x-2)+b*f(x-1)+c

並給你f(1),f(2)的值,請求出f(n)的值,由於f(n)的值可能過大,求出f(n)對1000007取模後的值。

注意:-1對3取模後等於2

輸入

第一行是乙個整數t,表示測試資料的組數(t<=10000)

隨後每行有六個整數,分別表示f(1),f(2),a,b,c,n的值。

其中0<=f(1),f(2)<100,-100<=a,b,c<=100,1<=n<=100000000 (10^9)

輸出 輸出f(n)對1000007取模後的值

樣例輸入

2

1 1 1 1 0 5

1 1 -1 -10 -100 3

樣例輸出

5

999896

** 經典題目

上傳者

張云聰

#include #include #include using namespace std;

#define len 1000007

typedef struct numb

}numb;

numb tem;//中間矩陣

numb x;//

numb y;

void set_x(numb &z,int a,int b)

void set_y(numb &z,int f1,int f2,int c)

void chenfa(numb &z,numb x,numb y)//a*b

void judge(numb &tmp,numb z,int n)//a的次方

n /= 2;

chenfa(z,z,z);

}}int main()

else

}return 0;

}

快速冪(矩陣快速冪)

求 3 0 3 1 3 n mod 1000000007 input 輸入乙個數n 0 n 10 9 output 輸出 計算結果 sample input 3sample output 40 分析 利用等比數列的求和公式得所求和是 3 n 1 1 2,如果暴力求3 n 1 會超時,這裡引入快速冪來...

快速冪 矩陣快速冪

快速冪 正常情況下求乙個數的冪時間複雜度為o n 而快速冪能把時間複雜度降到o logn 舉個例子 求5的13次方 思想首先把13化為二進位制 1101,即13 1101 8 1 4 1 2 0 1 1 即5 13 58 1 54 1 52 0 5 1 15 5 8 1 5 4 1 5 2 0 5 ...

快速冪 矩陣快速冪

快速冪 我們求a ba b ab最直接的方法就是把a乘b次這樣的話複雜度就是o n o n o n 但是在比賽時面對1e9的資料時還是會輕鬆超時的,此時就需要一種更快的乘法來幫助我們 我們把b拆成二進位制的形式得到a ba b ab a 10.01 a a1 0.01此時對b分解得到的序列10.01...