zoukankan      html  css  js  c++  java
  • 【HDU2604】Queuing

    题目链接

    Queuing

    题目描述

    Queues and Priority Queues are data structures which are known to most computer scientists. The Queue occurs often in our daily life. There are many people lined up at the lunch time.

    Now we define that ‘f’ is short for female and ‘m’ is short for male. If the queue’s length is (L), then there are (2L) numbers of queues. For example, if (L = 2), then they are (ff),(mm),(fm),(mf) . If there exists a subqueue as (fmf) or (fff), we call it O-queue else it is a E-queue.
    Your task is to calculate the number of E-queues mod (M) with length (L) by writing a program.

    输入格式

    Input a length (L)((0 le L le 10^6)) and (M).

    输出格式

    Output (K mod M)((1 le M le 30)) where (K) is the number of E-queues with length (L).

    样例输入

    3 8
    4 7
    4 8
    

    样例输出

    6
    2
    1
    

    题解

    题意:一个长度为(L)的序列,每个值为(f)(m),求序列中不包含(fmf)(fff)的序列的个数(mod M)的结果。
    看到这个我马上就想到了数位dp,但这题明显比数位dp简单很多。
    首先我们用(dp[j][i])表示前(j)个数最后两个数是(i),不包含(fmf)(fff)的序列的个数。
    (iin [0,3]),映射到(ff)(fm)(mf)(mm)上。
    这样的话转移方程就很容易写了。
    虽然这个dp时间复杂度是(O(n))的,但是有多组数据,实测会(T),所以我们可以用矩阵快速幂优化一下。
    矩阵的转移只有一层,所以直接按照转移方程构造矩阵就行了:

    注意要特判一下如果长度小于等与(2)的话,直接输出(2^L\%M)
    上代码:

    #include<bits/stdc++.h>
    using namespace std;
    int l,m;
    struct aa{
        int a[9][9];
    };
    aa x;
    aa cc(aa x,aa y){
        aa ans;
        for(int j=1;j<=4;j++)
            for(int i=1;i<=4;i++){
                ans.a[j][i]=0;
                for(int o=1;o<=4;o++)
                    ans.a[j][i]=(ans.a[j][i]+x.a[j][o]*y.a[o][i])%m;
            }
        return ans;
    }
    aa ksm(aa x,int p){
        aa ans;
        for(int j=1;j<=4;j++)
            for(int i=1;i<=4;i++)
                ans.a[j][i]=(j==i);
        while(p){
            if(p&1) ans=cc(ans,x);
            x=cc(x,x);
            p>>=1;
        }
        return ans;
    }
    int main(){
        x.a[1][2]=x.a[2][4]=x.a[3][1]=x.a[3][2]=x.a[4][3]=x.a[4][4]=1;
        while(scanf("%d%d",&l,&m)!=EOF){
            if(l==0){printf("0");continue;}
            if(l==1){printf("%d",2%m);continue;}
            if(l==2){printf("%d",4%m);continue;}
            aa ans=ksm(x,l-2);
            int anss=0;
            for(int j=1;j<=4;j++)
                for(int i=1;i<=4;i++)
                    anss=(anss+ans.a[j][i])%m;
            printf("%d
    ",anss);
        }
        return 0;
    }
    
  • 相关阅读:
    Java基础教程
    一个RDBMS左连接SQL执行计划解析
    hive时间日期函数及典型场景应用
    ETL数据采集方法
    数据仓库保存历史数据方法之拉链表
    NAS服务器局域网内IPad、手机、电视盒子等联网播放
    转:主流数据恢复软件——EasyRecovery/Ashampoo Undeleter/Wise Data Recovery/Recuva/Undelete 360
    [转]office2010一直卡在“正在受保护的视图中打开”
    [转]PROE传动链条的装配教程
    linux下svn定时更新项目
  • 原文地址:https://www.cnblogs.com/linjiale/p/13477464.html
Copyright © 2011-2022 走看看