hdu6030 Happy Necklace(矩阵快速幂+递推式)

思路来源

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

扫描二维码关注公众号,回复: 4349562 查看本文章

3 红红红 蓝红红 红蓝红 红红蓝 ans=4

4 红红红红 蓝红红红 红蓝红红 红红蓝红 红红红蓝 蓝红红蓝 ans=6

这么多就足以说明问题了,

注意到an至少等于an-1,

若第n个珠子为红,an-1的方案后补一个红珠即可,

若第n个珠子为蓝,由蓝蓝、蓝红蓝两种情况不能出现,

说明该种情况一定由XXXXX红红转移而来,XXXXX部分任意,对应an-3的方案数。

即有an=an1+an-3,矩阵快速幂一波就可以了。

\begin{bmatrix} a_{n+3}\\ a_{n+2}\\ a_{n+1}\\ \end{bmatrix}=\begin{bmatrix} 1 & 0 & 1\\ 1 & 0 & 0\\ 0 & 1 & 0 \end{bmatrix}*\begin{bmatrix} a_{n+2}\\ a_{n+1}\\ a_{n}\\ \end{bmatrix},一波矩阵快速幂即可

心得

还是得多做题,不然反应不过来,顺便屯个板子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; 
}

猜你喜欢

转载自blog.csdn.net/Code92007/article/details/83757547