1. 程式人生 > >hdu-2604 Queuing---遞推+矩陣快速冪

hdu-2604 Queuing---遞推+矩陣快速冪

其中 sin 一位 strong DC net name 思路 eof

題目鏈接:

https://vjudge.net/problem/HDU-2604

題目大意:

n個人排隊,f表示女,m表示男,包含子串‘fmf’和‘fff’的序列為O隊列,否則為E隊列,有多少個序列為E隊列。

解題思路:

用f(n)表示n個人滿足條件的結果,那麽如果最後一個人是m的話,那麽前n-1個滿足條件即可,就是f(n-1);
如果最後一個是f那麽這個還無法推出結果,那麽往前再考慮一位:那麽後三位可能是:mmf, fmf, mff, fff,其中fff和fmf不滿足題意所以我們不考慮,但是如果是
mmf的話那麽前n-3可以找滿足條件的即:f(n-3);如果是mff的話,再往前考慮一位的話只有mmff滿足條件即:f(n-4)


所以f(n)=f(n-1)+f(n-3)+f(n-4),遞推會超時,可用矩陣快速冪
構造一個矩陣:
技術分享圖片

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int MOD;
 4 struct Mat
 5 {
 6     int a[4][4];
 7     int n, m;//n為行數,m為列數
 8     Mat(int n, int m):n(n), m(m)
 9     {
10         memset(a, 0, sizeof(a));
11     }
12     void init()
13     {
14 for(int i = 0; i < n; i++)a[i][i] = 1;//初始化成單位矩陣 15 } 16 void output() 17 { 18 for(int i = 0; i < n; i++) 19 { 20 for(int j = 0; j < m; j++) 21 { 22 cout<<a[i][j]<<" "; 23 } 24 cout<<endl;
25 } 26 } 27 }; 28 Mat mul(Mat a, Mat b)//矩陣乘法 29 { 30 Mat tmp(a.n, b.m);//矩陣乘法結果矩陣行數為a的行數,列數為b的列數 31 for(int i = 0; i < a.n; i++) 32 { 33 for(int j = 0; j < b.m; j++) 34 { 35 for(int k = 0; k < a.m; k++)//a.m == b.n(乘法的前提條件) 36 { 37 tmp.a[i][j] += (a.a[i][k] * b.a[k][j] % MOD); 38 tmp.a[i][j] %= MOD; 39 } 40 } 41 } 42 return tmp; 43 } 44 Mat pow(Mat a, int n) 45 { 46 Mat tmp(a.n, a.m); 47 tmp.init(); 48 while(n) 49 { 50 if(n & 1)tmp = mul(tmp, a); 51 n /= 2; 52 a = mul(a, a); 53 } 54 return tmp; 55 } 56 int c[4][4] = 57 { 58 1,0,1,1, 59 1,0,0,0, 60 0,1,0,0, 61 0,0,1,0, 62 }; 63 int t[] = {0,2,4,6,9}; 64 int main() 65 { 66 Mat a(4, 4); 67 Mat b(4, 1); 68 memcpy(a.a, c, sizeof(c)); 69 for(int i = 0; i < 4; i++)b.a[i][0] = t[4 - i]; 70 //a.output(); 71 //b.output(); 72 int n ,k; 73 while(cin >> n >> k) 74 { 75 MOD = k; 76 if(n <= 4) 77 { 78 cout<<t[n]%k<<endl; 79 } 80 else 81 { 82 Mat ans = pow(a, n - 4); 83 ans = mul(ans, b); 84 //ans.output(); 85 cout<<ans.a[0][0]<<endl; 86 } 87 } 88 }

hdu-2604 Queuing---遞推+矩陣快速冪