hdu6030 (矩陣快速冪)
阿新 • • 發佈:2019-02-18
這道題讓我深深感到了線性代數的重要性啊,遞推關係式不是隨便搞搞就能出來的!
如果用a表示紅色,用b表示藍色。題意明顯可以看出只需要管長度2和3的連續序列是否符合!
如果以b結尾,那麼下一個必須是a,或者加個aab就可以了!
所以就是a[n]=a[n-1]+a[n-3];出現了n-3應該就是三維矩陣了!
矩陣要是從a【n-1】推導到a【n】,那麼令a【n-1】為第一維,
a[n]=a[n-1]+1[n-3],a[n-1]=a[n-1],a[n-2]=a[n-2];
得到矩陣
1 1 0
0 0 1
1 0 0
,有了矩陣就隨便搞搞啊,看有沒有初始矩陣啥的,特例啥的,這個很簡單推的。
2是特例,初始矩陣是
4 3 2
0 0 0
0 0 0
下面具體看程式碼
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<iostream> #include<algorithm> #include<stack> #include<queue> #include<vector> #include<set> #include<map> #include<string> using namespace std; typedef long long ll; const int INF=0x3f3f3f3f; const ll mod = 1e9 + 7; struct matrix { ll a[4][4]; matrix(){ memset(a,0,sizeof(a)); } }; matrix multi(matrix b,matrix a) { matrix c; for(int i=1;i<=3;i++){ for(int j=1;j<=3;j++){ if(a.a[i][j]==0) continue; for(int k=1;k<=3;k++){ c.a[i][k] = (c.a[i][k] + a.a[i][j] * b.a[j][k]) % mod; } } } return c; } matrix pow_matrix(matrix a,ll n) { matrix b; b.a[1][3] = b.a[2][1] = b.a[2][2]= b.a[3][2] = 1; while(n){ if(n&1) a = multi(b,a); b = multi(b,b); n>>=1; } return a; } int main() { int t; scanf("%d",&t); while(t--){ ll n; scanf("%lld",&n); if(n==2) printf("3\n"); else{ matrix ans; ans.a[1][1] = ans.a[1][2] = ans.a[1][3] = 1; ans = pow_matrix(ans,n-2); printf("%lld\n",(ans.a[1][1]+ans.a[1][2]+ans.a[1][3])%mod); } } }