题目链接:
题目描述:
给出n个六边形排成一排,a[i]代表i个六边形能组成的生成树个数,设定s[i]等于a[1]+a[2]+a[3]+....+a[i-1]+a[i],问s[n]为多少?
解题思路:
n取值范围[1, 1018],打表内存不够,然后就要考虑快速幂咯!纳尼!!!!快速幂写出来竟然超时,敢信?果然还是见题太少了。(GG)
对于a[n] = 6*a[n-1] - a[n-2],可以很明显看出。
然后求和的时候就要化简一番了,但是并不是很难,最终的公式是:s[n] = 6*s[n-1] - s[n-2] + 5;然后构造矩阵,预处理构造矩阵,跑快速幂即可!!
代码:
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #include <cstring> 8 using namespace std; 9 10 #define LL long long 11 const LL maxn = 3; 12 const LL mod = 1000000007; 13 struct mat 14 { 15 LL col, row; 16 LL p[maxn][maxn]; 17 } pp[65]; 18 19 mat mul (mat a, mat b); 20 mat pow (LL n, LL res, mat b); 21 22 int main () 23 { 24 LL n, t; 25 mat b; 26 scanf ("%lld", &t); 27 memset (pp[0].p, 0, sizeof(pp[0].p)); 28 memset (b.p, 0, sizeof(b.p)); 29 pp[0].col = pp[0].row = b.row = maxn; 30 b.col = 1; 31 pp[0].p[0][0] = 6; 32 pp[0].p[1][0] = -1; 33 pp[0].p[0][1] = pp[0].p[2][0] = pp[0].p[2][2] = 1; 34 b.p[0][0] = 6; 35 b.p[0][1] = 0; 36 b.p[0][2] = 5; 37 for (int i=1; i<65; i++) 38 pp[i] = mul(pp[i-1], pp[i-1]); 39 40 while (t --) 41 { 42 mat a; 43 scanf ("%lld", &n); 44 a = pow(n-1, 0, b); 45 printf ("%lld ", a.p[0][0] % mod); 46 } 47 48 return 0; 49 } 50 51 mat mul (mat a, mat b) 52 { 53 mat c; 54 c.col = a.col; 55 c.row = b.row; 56 memset (c.p, 0, sizeof(c.p)); 57 for (int k=0; k<a.row; k++) 58 for (int i=0; i<a.col; i++) 59 { 60 if (a.p[i][k] == 0) continue; 61 for (int j=0; j<b.row; j++) 62 { 63 if (b.p[k][j] == 0) continue; 64 c.p[i][j] = (c.p[i][j] + a.p[i][k] * b.p[k][j] + mod) % mod; 65 } 66 } 67 return c; 68 } 69 70 mat pow (LL n, LL res, mat b) 71 { 72 while (n) 73 { 74 if (n % 2) 75 b = mul (b, pp[res]); 76 res ++; 77 n /= 2; 78 } 79 return b; 80 }
写的好丑!不要喷我 (捂脸逃~~~~)