标签:namespace 程序 nbsp ret tle mode lan bubuko 题目
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1146 Accepted Submission(s): 491
如果用a表示红色,用b表示蓝色。题意明显可以看出只需要管长度2和3的连续序列是否符合!
如果以b结尾,那么下一个必须是a,或者加个aab就可以了!
先看这个特征方程F[i] = F[i - 1] + F[i - 3],那么就有一个矩阵如下
我们的目标矩阵就是
那么,针对这个矩阵我们如何转置呢?
先看目标矩阵第一个:F[i]
F[i] = F[i - 1] + F[i - 3]
那么,由矩阵乘法,转置矩阵第一行,似乎就定了:1 0 1
同样的,二三行就是1 0 0 和 0 1 0
整个矩阵如下:
#include<iostream> #include<algorithm> #include<cmath> #include<cstdio> #include<cstring> #define INF 0x3f3f3f3f #define mod 1000000007 using namespace std; typedef long long ll; const int maxn = 100010; ll n; struct Matrix { ll a[5][5]; }; Matrix mul(Matrix x, Matrix y) { Matrix temp; for (int i = 1; i <= 3; i++) for (int j = 1; j <= 3; j++) temp.a[i][j] = 0; for (int i = 1; i <= 3; i++) { for (int j = 1; j <= 3; j++) { ll sum = 0; for (int k = 1; k <= 3; k++) { sum = (sum + x.a[i][k] * y.a[k][j] % mod) % mod; } temp.a[i][j] = sum; } } return temp; } Matrix quickpow(Matrix A,ll k) { Matrix res; res.a[1][1] = 1; res.a[1][2] = 0; res.a[1][3] = 0; res.a[2][1] = 0; res.a[2][2] = 1; res.a[2][3] = 0; res.a[3][1] = 0; res.a[3][2] = 0; res.a[3][3] = 1; while (k) { if (k & 1) res = mul(res, A); A = mul(A, A); k >>= 1; } return res; } int main() { int t; scanf("%d", &t); while (t--) { scanf("%lld", &n); if (n == 2) { printf("3\n"); continue; } Matrix A; A.a[1][1] = 1; A.a[1][2] = 0; A.a[1][3] = 1; A.a[2][1] = 1; A.a[2][2] = 0; A.a[2][3] = 0; A.a[3][1] = 0; A.a[3][2] = 1; A.a[3][3] = 0; Matrix res = quickpow(A, n - 2); ll x = (res.a[1][1] + res.a[1][2] + res.a[1][3]) % mod; ll y = (res.a[2][1] + res.a[2][2] + res.a[2][3]) % mod; ll z = (res.a[3][1] + res.a[3][2] + res.a[3][3]) % mod; printf("%lld\n", (x + y + z) % mod); } }
2017中国大学生程序设计竞赛 - 女生专场 Happy Necklace(递推+矩阵快速幂)
标签:namespace 程序 nbsp ret tle mode lan bubuko 题目
原文地址:https://www.cnblogs.com/caiyishuai/p/9077211.html