HDU-2604 Queuing (矩阵快速幂 + 递推思想 + 通用版 )

HDU-2604 Queuing (矩阵快速幂 + 递推思想  + 通用版 )

Queuing

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)


Problem Description
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 2 L 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
Input a length L (0 <= L <= 10 6) and M.
 

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

Sample Input
 
  
3 84 74 8
 
Sample Output
 
  
621
 

Author
WhereIsHeroFrom
 

Source
 

Recommend
lcy   |   We have carefully selected several similar problems for you:   1588  1757  2606  2276  2603 

解题思路
递推思路, 若最后一个为m,则无论前一个为什么情况都可以,sum+=f[i-1]
                    若最后一个为f,则

                   若前一位为m,则再之前一位必定为m,

                                                    队列为mmf ,由mmf前一位决定,此时sum+=f[i-3]

                                                    若前一位为f,此时队列必为为mmff,由mmff前一位决定,此时sum+=f[i-4]

得递推式,f(n)=f(n-1)+f(n-3)+f(n-4);


手推 f(1)=2,f(2)=4,f(3)=6 f(4)=9;

fn-3       0 1 0 0                  f1

fn-2 =     0 0 1 0   ^(n-1)   f2

fn-1       0 0 0 1                 f3

fn          1 1 0 1                 f4


即造就了f(n)=f(n-1)+f(n-3)+f(n-4) 的式子。


#include <cstdio>
#include <cstring>
using namespace std;
int n,mod;
int init[4],lastans[4],base[4][4],ans[4][4];                       //由n-x的x决定
void mul(int b[4][4],int a[4][4],int tans[4][4])
{
     int i,j,k;
     int t[4][4];
     for(i=0;i<4;i++)
        for(j=0;j<4;j++)
        {
            t[i][j]=0;
            for(k=0;k<4;k++)
            t[i][j]=(t[i][j]+b[i][k]*a[k][j])%mod;      //在答案出取余就好
        }
     for(i=0;i<4;i++)
     for(j=0;j<4;j++)
     tans[i][j]=t[i][j]%mod;
 }
void pow_mod()    //base[][],ans[][],n定成全局变量了
{
        int i,j;
        init[0]=2;init[1]=4;init[2]=6;init[3]=9;          //init是初始列矩阵,初始的f值
        memset(base,0,sizeof(base));
        memset(ans,0,sizeof(ans));
        memset(lastans,0,sizeof(lastans));
        base[0][1]=1;base[1][2]=1;base[2][3]=1;           // base是初始累乘矩阵
        base[3][0]=1;base[3][1]=1;base[3][3]=1;
        ans[0][0]=ans[1][1]=ans[2][2]=ans[3][3]=1;       //ans一开始是单位阵
        while(n>0)                                       //n是次方的次数。
        {
                if((n&1)==1)
                mul(base,ans,ans);
                mul(base,base,base);
                n=n>>1;
        }
        for(i=0;i<4;i++)
        {
           for(j=0;j<4;j++)
          {
            lastans[i]+=ans[i][j]*init[j];    //在答案出取余就好
          }
        }
        for(i=0;i<4;i++)
        lastans[i]%=mod;
}
int main()
{
    while(scanf("%d%d",&n,&mod)!=EOF)
    {
        int p=n;
        n=n-4;
        pow_mod();
        if(p<=4)
        printf("%d\n",lastans[p-1]);
        else
        printf("%d\n",lastans[3]);
    }
    return 0;
}




猜你喜欢

转载自blog.csdn.net/xigongdali/article/details/80543545