思路来源
https://www.cnblogs.com/bolderic/p/7216739.html
题意
给你一个长为n的珠子串,要求你给这条串涂色,
要求任意素数长度的串中,红色数不少于蓝色数,只有红蓝两色。
问长为n的串的涂色方案数。
题解
这个递推式还是挺好想的,就是好久不用矩阵快速幂一下愣住了。
dp写久了小范围的用不了矩阵快速幂的还是把自己写傻了QAQ
注意到任意素数长度都成立,则任意2个必有1个红珠,任意3个必有2个红珠。
则剩下显然能推出5个必有3个,7个必有4个…以此类推,所以只看2个和3个即可。
1 红 蓝 ans=2
2 红红 蓝红 红蓝 ans=3
3 红红红 蓝红红 红蓝红 红红蓝 ans=4
4 红红红红 蓝红红红 红蓝红红 红红蓝红 红红红蓝 蓝红红蓝 ans=6
这么多就足以说明问题了,
注意到an至少等于an-1,
若第n个珠子为红,an-1的方案后补一个红珠即可,
若第n个珠子为蓝,由蓝蓝、蓝红蓝两种情况不能出现,
说明该种情况一定由XXXXX红红转移而来,XXXXX部分任意,对应an-3的方案数。
即有an=an1+an-3,矩阵快速幂一波就可以了。
=*,一波矩阵快速幂即可
心得
还是得多做题,不然反应不过来,顺便屯个板子gg
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <functional>
const int INF=0x3f3f3f3f;
const int maxn=1e5+10;
const int mod=1e9+7;
const int MOD=998244353;
const double eps=1e-7;
typedef long long ll;
#define vi vector<int>
#define si set<int>
#define pii pair<int,int>
#define pi acos(-1.0)
#define pb push_back
#define mp make_pair
#define lowbit(x) (x&(-x))
#define sci(x) scanf("%d",&(x))
#define scll(x) scanf("%lld",&(x))
#define sclf(x) scanf("%lf",&(x))
#define pri(x) printf("%d",(x))
#define rep(i,j,k) for(int i=j;i<=k;++i)
#define per(i,j,k) for(int i=j;i>=k;--i)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int inf = 0x3f3f3f3f;
typedef vector<long long> vec;
typedef vector<vec> mat;
mat mul(mat &A, mat &B){
mat C(A.size(), vec(B[0].size()));
for(int i = 0; i < A.size(); i++){
for(int k = 0; k < B.size(); k++){
for(int j = 0; j < B[0].size(); j++){
C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % mod;
}
}.j,j
}
return C;
}
mat pow(mat A, ll n){
mat B(A.size(), vec(A.size()));
for(int i = 0; i < A.size(); i++){
B[i][i] = 1;
}
while(n > 0){
if(n & 1) B = mul(B, A);
A = mul(A, A);
n >>= 1;
}
return B;
}
int main()
{
int t;
scanf("%d", &t);
while(t--){
long long n;
scanf("%lld", &n);
mat A(3, vec(3));
A[0][0] = 1; A[0][1] = 0; A[0][2] = 1;
A[1][0] = 1; A[1][1] = 0; A[1][2] = 0;
A[2][0] = 0; A[2][1] = 1; A[2][2] = 0;
A = pow(A, n - 2);
ll ans = (A[2][0] * 6 + A[2][1] * 4 + A[2][2] * 3) % mod;
printf("%lld\n", ans);
}
return 0;
}