hdu 6030 矩阵快速幂

来源:互联网 发布:淘宝买家秀网站 编辑:程序博客网 时间:2024/05/22 17:28


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

n的范围是10^18,那么只能用到矩阵快速幂:

可以推出最初的矩阵为 1 0 1

                                         1 0 0 

                                         0 1 0


#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<vector>#include<map>#include<string>using namespace std;#define clr(x,y) memset(x,y,sizeof x)const int maxn = 1000000 + 10;const double pp = 10e8;typedef long long ll;const ll SMod = 1000000007;struct Matrix{    ll m[3][3];};Matrix Mul(Matrix a,Matrix b){    Matrix c;    memset(c.m,0,sizeof(c.m));    for(ll i=0;i<3;i++)        for(ll j=0;j<3;j++)            for(ll k=0;k<3;k++)                c.m[i][j] += ((a.m[i][k]*b.m[k][j])%SMod + SMod)%SMod;    return c;}Matrix pow_mod(Matrix a,ll n){    Matrix res;    memset(res.m,0,sizeof(res.m));    res.m[0][0] = res.m[1][1] = res.m[2][2]  =  1;    while(n)    {        if(n&1)            res = Mul(res,a);        n>>=1;        a = Mul(a,a);    }    return res;}Matrix p ={    1,0,1,    1,0,0,    0,1,0};ll a[10];int main(){    ll Tcase;    scanf("%I64d",&Tcase);    a[2] = 3;    a[3] = 4;    a[4] = 6;    a[5] = 9;    while(Tcase --)    {        ll n;        scanf("%I64d",&n);        if(n <= 5)        {            printf("%I64d\n",a[n]);            continue;        }        Matrix t = pow_mod(p,n - 5);        ll ans = (t.m[0][0] * a[5] % SMod+ t.m[0][1] * a[4] %SMod + t.m[0][2] * a[3] %SMod ) % SMod;        printf("%I64d\n",ans);    }    return 0;}


0 0
原创粉丝点击