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

问题描述

小Q想给他的女朋友买一条项链。项链是由红色和蓝色的珠子组成的单串项链。
小Q拼命想给女朋友留下好印象,他知道她一定会喜欢这条项链的,只要对项链中每一个素数的连续子序列,红珠子的数量不小于蓝珠子的数量。
现在小Q想买一条正好有n颗珠子的项链。他想知道有多少种不同的项链能让他的女朋友开心。请编写一个程序来帮助小q。由于答案可能非常大,请打印出模109+7的答案。
注意:项链是单串的,不是圆的。

输入

输入的第一行包含一个整数T(1≤T≤10000),表示测试用例的数量。
对于每个测试用例,都有一行包含整数n(2≤n≤1018),表示项链上的珠子数。

输出

对于每个测试用例,打印包含单个整数的单行,表示答案的模109+7。

Sample Input

2
2
3

Sample Output

3
4

分析:

自己写的时候没想出来怎么推(以为要素数打表什么的)

看的别人的推导过程:
其实只需要考虑最小的质数2和3就行了
1.考虑在合法串的最后再加上一个红色,肯定可行
2.考虑在合法串的最后再加上一个蓝色,只有红红蓝可行
则式子为f[i]=f[i-1]+f[i-3]

然后弄出矩阵用矩阵快速幂求出答案就行了
(推出来的矩阵代码里面有)

code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<algorithm>
#include<sstream>
#define ll long long
//void fp(){freopen("1.txt","r",stdin);freopen("2.txt","w",stdout);}
const int inf=0x3f3f3f3f;
const int inn=-(1<<30);
using namespace std;
const int maxm=4;
struct Node{
    ll a[maxm][maxm];
    Node(){
        memset(a,0,sizeof a);
    }
};
const ll mod=1e9+7;
Node mul(Node aa,Node bb){
    Node s=Node();
    for(int i=0;i<3;i++){
        for(int j=0;j<3;j++){
            for(int k=0;k<3;k++){
                s.a[i][j]+=aa.a[i][k]*bb.a[k][j]%mod;
                s.a[i][j]%=mod;
            }
        }
    }
    return s;
}
Node ppow(Node a,ll b){
    Node ans=Node();
    ll cc[3]={6,4,3};//初始值直接塞这边
    for(int i=0;i<3;i++){
        ans.a[0][i]=cc[i];
    }
    while(b){
        if(b&1){
            ans=mul(ans,a);
        }
        a=mul(a,a);
        b>>=1;
    }
    return ans;
}
int main(){
    Node res;
    ll cc[3][3]={//转移矩阵
        1,1,0,
        0,0,1,
        1,0,0,
    };
    for(int i=0;i<3;i++){
        for(int j=0;j<3;j++){
            res.a[i][j]=cc[i][j];
        }
    }
    int T;
    cin>>T;
    ll aaa[5]={0,0,3,4,6};
    while(T--){
        ll n;
        cin>>n;
        if(n<=4){
            cout<<aaa[n]<<endl;;
            continue;
        }
        Node ans=ppow(res,n-4);
        cout<<ans.a[0][0]<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值