HDU5015 233 Matrix —— 矩阵快速幂
题目链接:https://vjudge.net/problem/HDU-5015
233 Matrix
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2805 Accepted Submission(s): 1611
For each case, the first line contains two postive integers n,m(n ≤ 10,m ≤ 109). The second line contains n integers, a1,0,a2,0,...,an,0(0 ≤ ai,0 < 231).
题解:
假设n = 4,则矩阵中第0列元素为:
a[0][0]
a[1][0]
a[2][0]
a[3][0]
a[4][0]
根据递推,第1列为:
a[0][1] = a[0][1]
a[1][1] = a[0][1] + a[1][0]
a[2][1] = a[0][1] + a[1][0] + a[2][0]
a[3][1] = a[0][1] + a[1][0] + a[2][0] + a[3][0]
a[4][1] = a[0][1] + a[1][0] + a[2][0] + a[3][0] + a[4][0]
第m列为:
a[0][m] = a[0][m]
a[1][m] = a[0][m] + a[1][m-1]
a[2][m] = a[0][m] + a[1][m-1] + a[2][m-1]
a[3][m] = a[0][m] + a[1][m-1] + a[2][m-1] + a[3][m-1]
a[4][m] = a[0][m] + a[1][m-1] + a[2][m-1] + a[3][m-1]+ a[4][m-1]
可发现当前一列可直接由上一列递推出来,因此构造矩阵:
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <cmath> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const int INF = 2e9; 15 const LL LNF = 9e18; 16 const int MOD = 10000007; 17 const int MAXN = 1e6+100; 18 19 const int Size = 12; 20 struct MA 21 { 22 LL mat[12][12]; 23 void init() 24 { 25 for(int i = 0; i<Size; i++) 26 for(int j = 0; j<Size; j++) 27 mat[i][j] = (i==j); 28 } 29 }; 30 31 MA mul(MA x, MA y) 32 { 33 MA ret; 34 memset(ret.mat, 0, sizeof(ret.mat)); 35 for(int i = 0; i<Size; i++) 36 for(int j = 0; j<Size; j++) 37 for(int k = 0; k<Size; k++) 38 ret.mat[i][j] += (1LL*x.mat[i][k]*y.mat[k][j])%MOD, ret.mat[i][j] %= MOD; 39 return ret; 40 } 41 42 MA qpow(MA x, LL y) 43 { 44 MA s; 45 s.init(); 46 while(y) 47 { 48 if(y&1) s = mul(s, x); 49 x = mul(x, x); 50 y >>= 1; 51 } 52 return s; 53 } 54 55 int main() 56 { 57 LL n, m, a[15]; 58 while(scanf("%lld%lld",&n,&m)!=EOF) 59 { 60 61 for(int i = 1; i<=n; i++) 62 scanf("%lld", &a[i]); 63 a[0] = 23; a[n+1] = 3; 64 65 MA s; 66 memset(s.mat, 0, sizeof(s.mat)); 67 for(int i = 0; i<=n; i++) 68 { 69 s.mat[i][0] = 10; 70 s.mat[i][n+1] = 1; 71 for(int j = 1; j<=i; j++) 72 s.mat[i][j] = 1; 73 } 74 s.mat[n+1][n+1] = 1; 75 76 s = qpow(s, m); 77 LL ans = 0; 78 for(int i = 0; i<=n+1; i++) 79 ans += 1LL*a[i]*s.mat[n][i]%MOD, ans %= MOD; 80 81 printf("%lld\n", ans); 82 } 83 }