HDU6030----矩阵快速幂
题意: 给出红蓝两种,然后排成一个字符串,要求在每一个长度为素数的区间里面是的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;
}
}

浙公网安备 33010602011771号