HDU - 6030 - Happy Necklace 【矩阵快速幂+思维+图解分析】

HDU - 6030 - Happy Necklace

Little Q wants to buy a necklace for his girlfriend. Necklaces are single strings composed of multiple red and blue beads.
Little Q desperately wants to impress his girlfriend, he knows that she will like the necklace only if for every prime length continuous subsequence in the necklace, the number of red beads is not less than the number of blue beads.
Now Little Q wants to buy a necklace with exactly nn beads. He wants to know the number of different necklaces that can make his girlfriend happy. Please write a program to help Little Q. Since the answer may be very large, please print the answer modulo 109+7 .
Note: The necklace is a single string, {not a circle}.

Input

The first line of the input contains an integer T(1T10000) , denoting the number of test cases.
For each test case, there is a single line containing an integer n(2n1018) , denoting the number of beads on the necklace.

Output

For each test case, print a single line containing a single integer, denoting the answer modulo 109+7.

Sample Input

2
2
3

Sample Output

3
4

题意:一个项链用n个珠子构成,是一个条而不是一个环,由红和蓝两种颜色构成,要求以任意点为起点向后的素数个珠子中,保证红颜色的大于等于蓝颜色的,问你有多少种方案满足,范围: n(2n1018)

分析: 我们知道最小的素数就是2了,由于考虑到是从任意一点开始,如果到了某一点往后没有两个的话就直接符合了,所以在n = 1的情况下,答案为2,也就是一个红,或一个蓝,首先我们可以在(n-1)项的基础上在末尾再添加一个红色,显然符合题意,其次我们考虑下因为最小的素数为2,所以不允许出现【蓝红蓝】的情况,但是可以出现【蓝红红蓝】的情况,所以当(n-1)项中后面连续两个是红色的时候我们就可以在末尾添加一个蓝色,我们可以发现(n-1)项中末尾是【红红】的数目恰好等于(n-3)的数目,可能不是很好理解,我把前五项列出来参考下便知晓了

这是前三项

这里写图片描述

我们再看下第四项

这里写图片描述
我们可以发现第四项的前四种是第三项后面添加一个红色,而后两种是在第三项中由第二项后面的红色再追加一个红色(有点拗口),也就是说当第三项的第1,3情况后面再添加一个蓝,而第三项的1,3项是由第二项1,3所构成的,而第二项的1,3是由第一项的所有构成的(这样说应该差不多了)

类似地我们再看第五项就好多了

这里写图片描述

参考代码

#include<bits/stdc++.h>
#define ll long long
#define mod(x) ((x)%MOD)

using namespace std;

const ll MOD = 1e9 + 7;

struct mat {
    ll m[3][3];
}a,ans,unit;
ll n;

void init() {
    memset(a.m,0,sizeof(a.m));
    memset(unit.m,0,sizeof(unit.m));
    unit.m[0][0] = 4;
    unit.m[0][1] = 3;
    unit.m[0][2] = 2;
    a.m[0][0] = 1;
    a.m[0][1] = 1;
    a.m[1][2] = 1;
    a.m[2][0] = 1;
}

mat operator * (mat m1,mat m2) {
    mat t;
    ll r;
    for(int i = 0;i < 3;i++) {
        for(int j = 0;j < 3;j++) {
            r = 0;
            for(int k = 0;k < 3;k++) {
                r = mod(r*1ll + mod(m1.m[i][k]*1ll*m2.m[k][j]));
            }
            t.m[i][j] = r;
        }
    }
    return t;
}

mat quick_pow(ll x) {
    mat t = unit;
    while(x) {
        if(x & 1) t = t*a;
        a = a*a;
        x >>= 1;
    }
    return t;
}

int main(){
    ios_base::sync_with_stdio(0);
    int T;cin>>T;
    while(T--) {
        init();
        cin>>n;
        if(n < 4) {
            if(n == 1) cout<<2<<endl;
            if(n == 2) cout<<3<<endl;
            if(n == 3) cout<<4<<endl;
            continue;
        }
        ans = quick_pow(1ll*n-3);
        cout<<ans.m[0][0]<<endl;
    }
    return 0;
}
  • 如有错误或遗漏,请私聊下UP,thx
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值