HDU-2604-Queuing(矩阵优化递推公式)

题目传送门
队列和优先级队列是大多数计算机科学家都知道的数据结构。排队在我们的日常生活中经常发生。午餐时间有许多人排队。

现在我们定义f是女性的缩写m是男性的缩写。如果队列长度为L,则有2L个队列。例如,如果L = 2,那么它们是ff mm fm mf。如果存在fmf或fff这样的子队列,我们称它为O-queue,否则它是一个E-queue。

您的任务是通过编写程序计算E-queues的数量,将M与长度L取余。

输入
输入长度L (0 <= L <= 10 [sup]6[/sup])和M。

输出
输出K对M(1 <= M <= 30)取余,其中K是长度为L的e队列数。

题解:
公式 f[n]=f[n-1]+f[n-3]+f[n-4];
当最后一个为m时 ——————————f[n-1];
最后一个为f时
fmm ————————————————f[n-3];
ffm 这种情况则必须为ffmm——————f[n-4];

搞一个矩阵快速幂就行了

#include <cstring>
#include <iostream>
#include <cstdio>
#define  m(a,b) memset(a,b,sizeof a)
typedef long long ll;
using namespace std;
const int N=10;
struct mat{ll a[N][N];};
ll n,mod;
mat mat_mul(mat x,mat y)
{
    mat res;
    m(res.a,0);
    for(int i=1;i<=4;i++)
        for(int j=1;j<=4;j++)
            for(int k=1;k<=4;k++)
                res.a[i][j]=(res.a[i][j]+(x.a[i][k]*y.a[k][j]%mod))%mod;
    return res;
}
mat mat_pow(int p)
{
    mat res,c;
    m(res.a,0);
    m(c.a,0);
    for(int i=1;i<=4;i++)
        res.a[i][i]=1;
    c.a[1][1]=c.a[1][3]=c.a[1][4]=c.a[2][1]=c.a[3][2]=c.a[4][3]=1;   //关系矩阵c
    while(p)
    {
        if(p&1)
            res=mat_mul(res,c);
        c=mat_mul(c,c);
        p>>=1;
    }
    return res;
}
int main()
{
    while(~scanf("%lld%lld",&n,&mod))
    {
        switch(n)
        {
            case 0:{printf("0\n");break;}
            case 1:{printf("%d\n",2%mod);break;}
            case 2:{printf("%d\n",4%mod);break;}
            case 3:{printf("%d\n",6%mod);break;}
            default:
                {
                    mat ans=mat_pow(n-3);
                    ll fin=(ans.a[1][1]*6+ans.a[1][2]*4+ans.a[1][3]*2+ans.a[1][4])%mod;
                    printf("%lld\n",fin);
                }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42576687/article/details/87216459