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。

    

 

#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;
}
posted on 2012-04-24 11:33  Staginner  阅读(276)  评论(0编辑  收藏  举报