题意: 给出红蓝两种,然后排成一个字符串,要求在每一个长度为素数的区间里面是的r(red)的数量不小与b(blue)的数量;
思路一:想象当n为2的时候的情况是 rr,rb,br,三种情况,当n为3的时候相当于在后面添加一个b或者r,会发现形成rr的情况是前面rr和br的和,形成br的情况是前面的rb,而形成rb的情况是前面的rr,不能有前面的br形成rb,因为在素数为3的时候不能形成brb;
所以你会发现这个针对的素数只是2和3;
根据递推,设数组a[],b[],c[]分别为后面两个字母为rr,br,rb的字符串的数量,那么可以得到递推式:
a[i] = a[i - 1] + c[i - 1];b[i] = a[i - 1];c[i] = b[i - 1];
而题中要求的是所有的字符串,即s[n] = a[n] + b[n] + c[n];
可以得出s[i] = s[i - 1] + s[i - 3];
思路二:考虑放第i个时的情况,如果放r则有S[n-1]种情况,如果放b则要求i-1和i-2的位置上必须都是r。则Si = S[i-1] + S[i-3];
由于数据有1018
所以考虑矩阵快速幂
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #define LL long long int #define R(i,n) for(int i = 0; i < n; i++) using namespace std; const LL mod = 1e9+7; struct node{ LL c[3][3]; } t,temp; LL n; node mul(node a,node b){//矩阵乘法 node c; int i,j,k; for(i=0;i<3;i++){ for(j=0;j<3;j++){ c.c[i][j]=0; for(k=0;k<3;k++) c.c[i][j]+=(a.c[i][k]*b.c[k][j])%mod; c.c[i][j]=c.c[i][j]%mod; } } return c; } node kuaisumi(LL n){ node res; memset(res.c,0,sizeof(res.c)); for(int i = 0; i < 3; i++) res.c[i][i] = 1; t.c[0][0] = 1;t.c[0][1] = 1;t.c[0][2] = 0; t.c[1][0] = 0;t.c[1][1] = 0;t.c[1][2] = 1; t.c[2][0] = 1;t.c[2][1] = 0;t.c[2][2] = 0; if(n<0) return res; while(n){ if(n&1) res=mul(res,t); t=mul(t,t); n=n>>1; } return res; } int main(){ //freopen("C:\Users\admin\Desktop\1.in","r",stdin); //freopen("C:\Users\admin\Desktop\1.out","w",stdout); std::ios::sync_with_stdio(false); int T_T; cin>>T_T; while(T_T--){ cin>>n; LL a[] = {0,2,3,4,6}; if(n <= 4){ cout<<a[n]<<endl; continue; } node ret = kuaisumi(n-4); cout<<(a[4]*ret.c[0][0]+a[3]*ret.c[1][0]+a[2]*ret.c[2][0])%mod<<endl; } }