题目传送门
队列和优先级队列是大多数计算机科学家都知道的数据结构。排队在我们的日常生活中经常发生。午餐时间有许多人排队。
现在我们定义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);
}
}
}
}