HDU 2604 Queuing

HDU_2604

    由于L比较大,我们可以设法得到E-queues的递推式后用二分矩阵的方法简化运算。

    接下来我们要考虑递推到n时新生成的E-queues,显然只考虑n-1时E-queues的最后两位的情况即可。不妨设a[n]表示结尾为fm的数量,b[n]为结尾为ff的数量,c[n]为结尾为mf的数量,d[n]为结尾为mm的数量,那么就有a[n]=b[n-1]+c[n-1],b[n]=c[n-1],c[n]=d[n-1],d[n]=a[n-1]+d[n-1],写成矩阵形式就是下图。进而就可以得到矩阵形式的通项公式了,然后二分矩阵就可以了,最后的结果就是a[n]+b[n]+c[n]+d[n],边界值为a[2]=b[2]=c[2]=d[2]=1。

    HDU 2604 Queuing

 

#include<stdio.h>

#include<string.h>

#define MAXD 4

int L, M, cnt;

struct Matrix

{

    int a[MAXD][MAXD];

    void init()

    {

        memset(a, 0, sizeof(a));

        a[0][1] = a[0][2] = a[1][2] = a[2][3] = a[3][0] = a[3][3]= 1;

    }

}mat[150];

int multiply(int x, int y)

{

    int i, j, k, z = ++ cnt, ans;

    for(i = 0; i < 4; i ++)

        for(j = 0; j < 4; j ++)

        {

            ans = 0;

            for(k = 0; k < 4; k ++)

                ans += mat[x].a[i][k] * mat[y].a[k][j];

            mat[z].a[i][j] = ans % M;

        }

    return z;

}

int powmod(int n)

{

    int k;

    if(n == 1)

        return 0;

    k = powmod(n / 2);

    k = multiply(k, k);

    if(n & 1)

        k = multiply(k, 0);

    return k;

}

void solve()

{

    int i, j, k, ans = 0;

    cnt = 0;

    mat[0].init();

    k = powmod(L - 2);

    for(i = 0; i < 4; i ++)

        for(j = 0; j < 4; j ++)

            ans += mat[k].a[i][j];

    printf("%d\n", ans % M);

}

int main()

{

    while(scanf("%d%d", &L, &M) == 2)

    {

        if(L == 0)

            printf("0\n");

        else if(L <= 2)

            printf("%d\n", 1 << L);

        else

            solve();

    }

    return 0;

}

你可能感兴趣的:(HDU)