您的位置:首页 > 产品设计 > UI/UE

hdoj 4062 Queuing 【矩阵快速幂优化递推公式】

2015-08-31 16:43 375 查看

Queuing

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

Total Submission(s): 3609 Accepted Submission(s): 1629



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




题意:给你一个只由字符m和f组成的长度为L的序列,我们令存在子序列fmf或fff的序列为O-序列,其它的序列均为E-序列。现在让你求出K % M,其中K为长L的序列里面E-序列的数目。



思路:这道题需要先推出公式f(L) = f(L-1) + f(L-3) + f(L-4)。然后同求斐波那契数列的方式,构造矩阵,下面就是矩阵快速幂了。

公式推导:

我们考虑L长序列的最后一位字符C1

一:C1 = m,我们不用考虑前面L-1字符,直接有方案数f(L-1);

二:C1 = f,我们需要考虑L长序列的倒数第二个字符C2

1,C2 = m,因为末尾序列可能存在fmf的情况,我们需要考虑L长序列的倒数第三个字符C3

(1) C3 = m,得到末尾三个字符mmf,我们不用考虑mmf前面的字符,有方案数f(L-3);

(2) C4 = f,得到末尾三个字符fmf,不是E-序列。

2,C2 = f,因为末尾序列可能存在fff的情况,我们需要考虑L长序列的倒数第三个字符C3

(1) C3 = m,得到末尾三个字符mff,因为末尾序列可能存在fmff的情况,我们考虑倒数第四个字符C4

One C4 = m,得到末尾序列mmff,我们不用考虑mmff前面的字符,有方案数f(L-4);

TwoC4 = f,得到末尾序列fmff,不是E-序列。

(2) C4 = f,得到末尾三个字符fff,不是E-序列。
这样总方案数f(L) = f(L-1) + f(L-3) + f(L-4)。

下面就是构造矩阵了,给个图示

初始矩阵 F矩阵



构造矩阵后,求出初始矩阵的L-3次幂,最后再与F矩阵相乘得到结果矩阵Ans。最后的答案就是Ans[0]。

这里说的是L>3的情况,至于L <= 3的情况只需要注意L = 0时结果是0就行了。

AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 6
#define LL long long
using namespace std;
struct Matrix
{
    int a[MAXN][MAXN];
    int r, c;
};
Matrix ori, res;
int F[5];//F矩阵
int Ans[5];//结果矩阵
void init()
{
    //构造矩阵
    ori.r = ori.c = 4;
    memset(ori.a, 0, sizeof(ori.a));
    ori.a[0][0] = ori.a[0][2] = ori.a[0][3] = 1;
    ori.a[1][0] = ori.a[2][1] = ori.a[3][2] = 1;
    //构造单位矩阵
    res.r = res.c = 4;
    memset(res.a, 0, sizeof(res.a));
    res.a[0][0] = res.a[1][1] = res.a[2][2] = res.a[3][3] = 1;
    //构造F矩阵
    F[0] = 6, F[1] = 4, F[2] = 2, F[3] = 1;
}
Matrix muitl(Matrix x, Matrix y, int m)
{
    Matrix z;
    memset(z.a, 0, sizeof(z.a));
    z.r = x.r; z.c = y.c;
    for(int i = 0; i < x.r; i++)
    {
        for(int k = 0; k < x.c; k++)
        {
            if(x.a[i][k] == 0) continue;
            for(int j = 0; j < y.c; j++)
                z.a[i][j] = (z.a[i][j] + (x.a[i][k] * y.a[k][j]) % m) % m;
        }
    }
    return z;
}
void Matrix(int n, int m)
{
    while(n)
    {
        if(n & 1)
            res = muitl(ori, res, m);
        ori = muitl(ori, ori, m);
        n >>= 1;
    }
}
void solve(int n, int m)
{
    Matrix(n, m);//矩阵的n次幂 对m取余
    memset(Ans, 0, sizeof(Ans));
    for(int i = 0; i < res.r; i++)
    {
        for(int k = 0; k < res.c; k++)
            Ans[i] = (Ans[i] + res.a[i][k] * F[k]) % m;
    }
    printf("%d\n", Ans[0]);
}
int main()
{
    int L, M;
    while(scanf("%d%d", &L, &M) != EOF)
    {
        Ans[0] = 0, Ans[1] = 2, Ans[2] = 4, Ans[3] = 6;
        if(L <= 3)
        {
            printf("%d\n", Ans[L] % M);
            continue;
        }
        init();//构造矩阵
        solve(L-3, M);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: