FZoj--2117(DP,矩阵快速幂)
2014-11-18 17:25:19
思路:dp[i][a][b],表示确定了i个数位,7的奇偶情况是a,9的奇偶情况是b,然后发现n很大,显然用矩阵加速。
右侧单列矩阵四个元素分别是:奇奇、奇偶、偶奇、偶偶的情况,然后构造一下左侧矩阵就行了。
(这里可以把4*4矩阵优化成3*3,因为发现奇偶和偶奇的情况值是一样的,思考)
注意:把算过的转移矩阵记忆下来能优化不少的时间。
1 /************************************************************************* 2 > File Name: 2117.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Tue 18 Nov 2014 04:23:57 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 const int mod = 1000000007; 27 28 int T,cnt; 29 ll n; 30 31 struct Mx{ 32 ll a[3][3]; 33 void clear(){ memset(a,0,sizeof(a));} 34 void stand(){ memset(a,0,sizeof(a)); for(int i = 0; i < 3; ++i) a[i][i] = 1;} 35 Mx operator * (Mx b){ 36 Mx c; 37 c.clear(); 38 for(int i = 0; i < 3; ++i){ 39 for(int j = 0; j < 3; ++j){ 40 for(int k = 0; k < 3; ++k){ 41 c.a[i][j] = (c.a[i][j] + (a[i][k] * b.a[k][j]) % mod) % mod; 42 } 43 } 44 } 45 return c; 46 } 47 }; 48 49 Mx t[100]; 50 51 Mx Q_pow(ll num){ 52 Mx res,tem = t[1]; 53 int v = 1; 54 res.stand(); 55 while(num){ 56 if(num & 1) res = res * tem; 57 v++; 58 if(cnt >= v) tem = t[v]; 59 else{ 60 tem = tem * tem; 61 t[++cnt] = tem; 62 } 63 num >>= 1; 64 } 65 return res; 66 } 67 68 int main(){ 69 cnt = 1; 70 t[1].clear(); 71 t[1].a[0][0] = 3; 72 t[1].a[0][1] = 2; 73 t[1].a[1][0] = 1; 74 t[1].a[1][1] = 3; 75 t[1].a[1][2] = 1; 76 t[1].a[2][1] = 2; 77 t[1].a[2][2] = 3; 78 scanf("%d",&T); 79 while(T--){ 80 scanf("%I64d",&n); 81 Mx ans; 82 ans.clear(); 83 ans.a[2][0] = 1; 84 ans = Q_pow(n) * ans; 85 printf("%I64d\n",ans.a[2][0]); 86 } 87 return 0; 88 }