矩阵快速幂+构造方法
與快速冪一樣,可以將遞推式通過二進制的方式來進行優化,這個學了快速冪就是十分容易理解
大概的板子如下:
struct mat///自己定義大小的矩陣
{ll m[11][11];
};
mat mulmat(mat A,mat B)///兩個矩陣相乘
{mat C;memset(C.m,0,sizeof(C.m));for(int i=0;i<n;i++)///注意n是自己構造矩陣的大小for(int j=0;j<n;j++)for(int k=0;k<n;k++)C.m[i][j]=(C.m[i][j]+A.m[i][k]*B.m[k][j])%mod;return C;
}
mat qmod_mat(mat A,ll b)///A為變換矩陣,b為冪
{mat ans;memset(ans.m,0,sizeof(ans.m));for(int i=0;i<10;i++) ans.m[0][i]=i;///給自己的初始矩陣賦值,一般初始矩陣和變換矩陣都是固定的while(b){if(b&1) ans=mulmat(ans,A);A=mulmat(A,A);b>>=1;}return ans;///最后的矩陣,答案
}
int main()
?
這個與快速冪寫法略有不同,主要是因為矩陣快速冪需要自己構造你的變換函數,而快速冪的a僅僅是一個底數。
構造矩陣快速冪的方法是這種題的重要難點:
矩陣構造方法
Fibonacci數列:F(0)=1 , F(1)=1 , F(n)=F(n-1)+F(n-2)
我們以前快速求Fibonacci數列第n項的方法是 構造常系數矩陣
(一)?? Fibonacci數列f[n]=f[n-1]+f[n-2],f[1]=f[2]=1的第n項快速求法(不考慮高精度)
解法:
考慮1×2的矩陣【f[n-2],f[n-1]】。根據Fibonacci數列的遞推關系,我們可以通過乘以一個2×2的矩陣A,得到矩陣:【f[n-1],f[n]】。
即:【f[n-2],f[n-1]】*A = 【f[n-1],f[n]】=【f[n-1],f[n-1]+f[n-2]】
很容易構造出這個2×2矩陣A,即:
0 1?
1 1
所以,有【f[1],f[2]】×A=【f[2],f[3]】
又因為矩陣乘法滿足結合律,故有:
【f[1],f[2]】×A ^(n-1) =【f[n],f[n+1]】
這個矩陣的第一個元素f[n]即為所求。
?
(二)?? 數列f[n]=f[n-1]+f[n-2]+1,f[1]=f[2]=1的第n項的快速求法(不考慮高精度)
解法:
仿照前例,考慮1×3的矩陣【f[n-2],f[n-1],1】,希望求得某3×3的矩陣A,使得此1×3的矩陣乘以A得到矩陣:【f[n-1],f[n],1】
即:【f[n-2],f[n-1],1】* A =【f[n-1],f[n],1】=【f[n-1],f[n-1]+f[n-2]+1,1】
容易構造出這個3×3的矩陣A,即:
0 1 0?
1 1 0?
0 1 1
故:【f[1],f[2],1】* A^(n-1) = 【f[n],f[n+1],1】
?
(三)數列f[n]=f[n-1]+f[n-2]+n+1,f[1]=f[2]=1的第n項的快速求法(不考慮高精度).
解法:
仿照前例,考慮1×4的矩陣【f[n-2],f[n-1],n,1】,希望求得某4×4的矩陣A,使得此1×4的矩陣乘以A得到矩陣:【f[n-1],f[n],n+1,1】
即:【f[n-2],f[n-1],n,1】* A? = 【f[n-1],f[n],n+1,1】=【f[n-1],f[n-1]+f[n-2]+n+1,n+1,1】
容易構造出這個4×4的矩陣A,即:
0 1 0 0?
1 1 0 0?
0 1 1 0?
0 1 1 1
故:【f[1],f[2],3,1】* A^(n-1) = 【f[n],f[n+1],n+2,1】
?
?
(四)?? 數列f[n]=f[n-1]+f[n-2],f[1]=f[2]=1的前n項和s[n]=f[1]+f[2]+……+f[n]的快速求法(不考慮高精度).
解法:
仿照之前的思路,考慮1×3的矩陣【f[n-2],f[n-1],s[n-2]】,我們希望通過乘以一個3×3的矩陣A,得到1×3的矩陣:【f[n-1],f[n],s[n-1]】
即:【f[n-2],f[n-1],s[n-2]】 * A? = 【f[n-1],f[n],s[n-1]】=【f[n-1],f[n-1]+f[n-2],s[n-2]+f[n-1]】
容易得到這個3×3的矩陣A是:
0 1 0?
1 1 1?
0 0 1
這種方法的矩陣規模是(r+1)*(r+1)
f(1)=f(2)=s(1)=1 ,所以,有
【f(1),f(2),s(1)】* A? = 【f(2),f(3),s(2)】
故:【f(1),f(2),s(1)】* A^(n-1)? = 【f(n),f(n+1),s(n)】
?
(五)?? 數列f[n]=f[n-1]+f[n-2]+n+1,f[1]=f[2]=1的前n項和s[n]=f[1]+f[2]+……+f[n]的快速求法(不考慮高精度).
解法:
考慮1×5的矩陣【f[n-2],f[n-1],s[n-2],n,1】,
我們需要找到一個5×5的矩陣A,使得它乘以A得到如下1×5的矩陣【f[n-1],f[n],s[n-1],n+1,1】
即:【f[n-2],f[n-1],s[n-2],n,1】* A? =【f[n-1],f[n],s[n-1],n+1,1】
=【f[n-1], f[n-1]+f[n-2]+n+1,s[n-2]+f[n-1],n+1,1】
容易構造出A為:
0 1 0 0 0?
1 1 1 0 0?
0 0 1 0 0?
0 1 0 1 0?
0 1 0 1 1
故:【f(1),f(2),s(1),3,1】* A^(n-1)? = 【f(n),f(n+1),s(n),n+2,1】
?
一般地,如果有f[n]=p*f[n-1]+q*f[n-2]+r*n+s
可以構造矩陣A為:
0? q ?0 ?0 ?0?
1 ?p ?1 ?0 ?0?
0 ?0 ?1 ?0 ?0?
0 ?r ?0 ?1 ?0?
0 ?s ?0 ?1 ?1
更一般的,對于f[n]=Sigma(a[n-i]*f[n-i])+Poly(n),其中0<i<=某常數c, Poly (n)表示n的多項式,我們依然可以構造類似的矩陣A來解決問題。
設Degree(Poly(n))=d, 并規定Poly(n)=0時,d=-1,此時對應于常系數線性齊次遞推關系。則本方法求前n項和的復雜度為:
((c+1)+(d+1))3*logns
例如:A(0) = 1 , A(1) = 1 , A(N) = X * A(N - 1) + Y * A(N - 2) (N >= 2);給定三個值N,X,Y求S(N):S(N) = A(0)2 +A(1)2+……+A(n)2。
解:考慮1*4 的矩陣【s[n-2],a[n-1]^2,a[n-2]^2,a[n-1]*a[n-2]】
我們需要找到一個4×4的矩陣A,使得它乘以A得到1×4的矩陣
【s[n-1],a[n]^2,a[n-1]^2,a[n]*a[n-1]】
即:【s[n-2],a[n-1]^2,a[n-2]^2,a[n-1]*a[n-2]】* A = 【s[n-1],a[n]^2,a[n-1]^2,a[n]*a[n-1]】
= 【s[n-2]+a[n-1]^2 , x^2 * a[n-1]^2 + y^2 * a[n-2]^2 + 2*x*y*a[n-1]*a[n-2] ,
a[n-1]^2 , x*a[n-1]^2 + y*a[n-2]a[n-1]】
可以構造矩陣A為:
1???? 0??? 0??? 0
1??? x^2?? 1??? x
0??? y^2?? 0??? 0
0??? 2xy?? 0??? y
故:【S[0],a[1]^2,a[0]^2,a[1]*a[0]】 * A^(n-1) = 【s[n-1],a[n]^2,a[n-1]^2,a[n]*a[n-1]】
所以:【S[0],a[1]^2,a[0]^2,a[1]*a[0]】 * A^(n) = 【s[n],a[n+1]^2,a[n]^2,a[n+1]*a[n]】
若A = (B * C ) 則AT?= ( B * C )T?= CT?* BT
附:大佬博客鏈接
總結
以上是生活随笔為你收集整理的矩阵快速幂+构造方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDU - 5874 Friends
- 下一篇: HDU 3306 Another kin