矩陣二分快速冪優化dp

2021-08-16 19:44:23 字數 2158 閱讀 8709

思路就是先寫出dp的狀態轉移方程,然後再把它轉成形如 [f[i], f[i-1]]= a * [f[i-1], f[i-2]] 的形式,(尤其是看到要求的i值取值範圍很大時,明白不能普通dp了不然容易超時)然後由「矩陣二分快速冪」來快速直接求得f[i],而不用像普通dp一樣乙個乙個向上做。

(2018/3/31)又默碼了一遍,發現有些細節不得不提——首先是相乘是一定要注意順序的,比如在main函式裡將乘好次方的結果和初始矩陣相乘時,初始矩陣要在右邊。第二點是我自己寫的時候矩陣維度不像下面一樣給你定了,而是作為了函式引數,那麼就應該清晰一點(因為在matrix_pow函式中慣性思維是用次數n來for迴圈矩陣快速冪,而我粗心將傳入的矩陣維度引數宣告為n,就搞錯了)。其次,要記住在矩陣相乘的時候把係數(對應的地方)都看好,然後要記得取模。最後,要記得用long long!因為既然你用到矩陣二分快速冪了,那麼一定就是大資料才會去用的,那麼記得次數n用long long!

btw,在手寫推導矩陣時,注意如果遇到什麼常數相加還是有辦法解決的,畢竟常數*0=0,*1=本身,比如

int n; // 所有矩陣都是 n * n 的矩陣

struct matrix ;

matrix matrix_mul(matrix a, matrix b, int mod) }}

return c;

}matrix unit() else }}

return res;

}matrix matrix_pow(matrix a, int n, int mod)

temp = matrix_mul(temp, temp, mod);

}return res;

}

應用:

我的ac**

#include#includeusing namespace std;

const int maxn=5;

struct matrix

;long long mod;

matrix mul(matrix a, matrix b) //矩陣乘法

最主要的是找到狀態轉移方程:

a[i]=b[i-1]*y/100 + a[i-1](1-x/100)

b[i]=a[i-1]*x/100 + b[i-1](1-y/100)

然後把它寫成[a[i]; b[i]] = a * [a[i-1];b[i-1]] ,寫出這個2*2的矩陣a,就可以套模板了。

#include#includeusing namespace std;

const int maxn=5;

struct matrix

;matrix mul(matrix a, matrix b) //矩陣乘法

; //關鍵!!!!!

for(int i=0;i>=1)

a=mul(a,a);

}matrix start=res(2,1);

start.m=2; start.n=1;

double bb[2][1]=;

for(int i=0;i

for(int j=0;j

start.a[i][j]=bb[i][j];

matrix result=mul(e,start);

printf("%f %f",result.a[0][0],result.a[1][0]);

return 0;

}

二分快速冪

在a,b為整數時,若 b很大,如 b 10 25 的時候,我們就要進行優化。如果b是偶數,則可以看作 a b a b 2 2 如果b是奇數,則 a b a b 1 2 2。則有兩種方法,一種遞迴 dfs 一種迴圈,遞迴如下 int dfs int a,int b,int mod int temp d...

二分快速冪

題目 ac include includeusing namespace std long long pow long long a,long long b,long long mod 二分快速冪 int main long long n,m cin n m long long mod 100000...

二分快速冪

對於a b,普通的求法是用乙個迴圈一直乘b個a,這樣的方法對於某些題目來說可能顯得比較慢。二分快速冪是一種利用b的二進位制特徵來快速求a b的演算法。例如 a 2,b 35 則b的二進位制表示形式為100011 則 a b 2 32 2 2 2 1 有了這樣的思路之後,就不用迴圈b次了。假設b的二進...