2 2 3
3 4
由於2是最小的素數,考慮長度爲2的子串。紅色爲A,藍色爲B,則只有AA,AB,BA三種狀況。對每種狀況,在後面加上A或B,AA能夠造成AA,AB,AB能夠造成BA,BA能夠造成AA。經過這個遞推擴展到長度爲n的狀況,用矩陣快速冪加速便可。矩陣爲:php
初始狀況下,AA,AB,BA都有可能,所以最後將矩陣中的全部數字相加就是答案。ios
注意n爲10的18次方會爆int因此在矩陣快速冪的時候要用long long【Matrix quickpow(Matrix A,ll k)】app
#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); } }
1018
101Matrix quickpow(Matrix A,ll k)】1018101810181018101810181018101810less