1. 程式人生 > >【HDU2604】Queuing(矩陣快速冪+遞推)

【HDU2604】Queuing(矩陣快速冪+遞推)

題目連結

Queuing

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7343    Accepted Submission(s): 3232


 

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 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

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 8 4 7 4 8

 

 

Sample Output

 

6 2 1

 

【題意】

有一個2^L長的隊伍,隊伍中有f和m,當隊伍中存在fmf或fff這兩種情況的子佇列時該隊伍為O佇列,否則為E佇列,求解給定長度的E佇列的方案數。

【解題思路】

題解參考大佬部落格:https://blog.csdn.net/jnxxhzz/article/details/83025739

假設dp[n]表示長度為n的E序列的方案數,第n個位置可以放f或m。

1.若第n個位置放m,那麼第n-1個位置可以放f,m,這兩種情況都不會變成O佇列,所以第n-1個位置的狀態可以被轉移。

2.若第n個位置放f,那麼第n-1個位置放f還是m不確定,因為都有可能會構成O佇列。

(1)當第n-1個位置放m,那麼第n-2個位置只能放m,所以第n-3個位置的狀態可以被轉移。

(2)當第n-1個位置放f,那麼第n-2個位置只能放m,但是第n-3個位置如果放f也是會構成O佇列的,所以第n-3個位置也只能放m,所以第n-4個位置的狀態可以被轉移。

最後f(n)=f(n-1)+f(n-3)+f(n-4),就是矩陣快速冪模板題啦。

【程式碼】

#include<bits/stdc++.h>
using namespace std;
int n,mod;
int f[5]={1,2,4,6,9};
struct Matrix
{
    int a[4][4];
    void init()
    {
        memset(a,0,sizeof(a));
        for(int i=0;i<4;i++)
            a[i][i]=1;
    }
};
Matrix mul(Matrix a,Matrix b)
{
    Matrix ans;
    for(int i=0;i<4;i++)
    {
        for(int j=0;j<4;j++)
        {
            ans.a[i][j]=0;
            for(int k=0;k<4;k++)
                ans.a[i][j]=(ans.a[i][j]+(a.a[i][k]*b.a[k][j])%mod)%mod;
        }
    }
    return ans;
}
Matrix quick_pow(Matrix a,int n)
{
    Matrix ans;
    ans.init();
    while(n)
    {
        if(n&1)ans=mul(ans,a);
        a=mul(a,a);
        n>>=1;
    }
    return ans;
}
int main()
{
    while(~scanf("%d%d",&n,&mod))
    {
        if(n<=4)
        {
            printf("%d\n",f[n]%mod);
            continue;
        }
        Matrix x;
        memset(x.a,0,sizeof(x.a));
        x.a[0][0]=x.a[0][2]=x.a[0][3]=x.a[1][0]=x.a[2][1]=x.a[3][2]=1;
        x=quick_pow(x,n-4);
        int ans=0;
        for(int i=0;i<4;i++)
        {
            int t=(x.a[0][i]*f[4-i])%mod;
            ans=(ans+t)%mod;
        }
        printf("%d\n",ans%mod);
    }
    return 0;
}