问题描述
小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;
}