zoukankan      html  css  js  c++  java
  • 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;
        }
    }
    

      

  • 相关阅读:
    SQL 查询两个时间段是否有交集的情况 三种写法
    c# 时间区间求并集
    uniapp 身份证识别 微信 百度 图片前端压缩 图片后端压缩
    Git命令大全
    构建android studio项目
    如何查tomcat进程和杀死进程
    mysql 备份 还原不了
    解决git extensions每次要输入用户名和密码
    JS string 转 Byte64[]
    Git cmd
  • 原文地址:https://www.cnblogs.com/OMG-By/p/7272474.html
Copyright © 2011-2022 走看看