hdu2604 Queuing
题意:
f代表女性,m代表男性,排成纵队,长度为L的队列方案数有2^L种,如果某个队列存在"fmf"或"fff"子队列,那么这个队列是O-queue,否则是E-queue
求E-queue的数目%MOD后的值
思路:
用f(n)表示n长度的E序列数目,此题倒推
如果最后一位是m,前面无限制,求f(n-1)即可
如果最后一位是f,前面有限制,往前推一位,mf ff,这两个都有限制,再往前推一位,fmf mmf fff mff,其中fmf和fff不符合条件我们不考虑,
如果是mmf,前面无限制,求f(n-3)即可,
如果是mff,前面有限制,往前推一位,fmff mmff,fmff不符合条件我们不考虑,mmff前面无限制,求f(n-4)即可
至此,对于当前的f(n)来说,所有情况都已考虑到,我们可以写出式子:
f(n) = f(n-1) + f(n-3) + f(n-4)
显然不能直接递归,时间会跪,所以我们转化成矩阵
看大神说也可以用trie图表示,有字符串fmf和fff构建trie图
假定根节点为字符串的最后一个字符,由根结点到根节点的回路有m、fmm、ffmm,注意这是从一个字符串的后面向前走这些字符到达另一个字符串,恰好和上面的扩展递推相一致
这个图还是比较迷的……
代码:
/**************************************************************
Problem: HDU_2604
User: soundwave
Language: C++
Result: Accepted
Time: 280ms
Memory: 1576KB
****************************************************************/
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <stdio.h>
#include <vector>
/*
感觉这个推公式还是比较麻烦的,因为还有许多重复项
所以还是推出关系式,用矩阵乘法求比较好
f(n) = f(n-1) + f(n-3) + f(n-4);
A^
*/
using namespace std;
typedef vector<int>Vint;
typedef vector<Vint>VVint;
typedef __int64 LL;
int MOD;
//矩阵乘法
VVint calc(VVint &A, VVint &B){
VVint C(A.size(), Vint(A.size()));
for(int i=0; i<A.size(); i++)
for(int j=0; j<B[0].size(); j++)
for(int k=0; k<B.size(); k++)
C[i][j] = (C[i][j] + (A[i][k]*B[k][j])%MOD) % MOD;
return C;
}
//二分快速幂
VVint my_pow(VVint &A, int c){
VVint B(A.size(), Vint(A.size()));
for(int i=0; i<A.size(); i++)
B[i][i] = 1;
if(c==1) return A;
while(c>0){
if(c&1) B = calc(B,A);
A = calc(A,A);
c>>=1;
}
return B;
}
int main(){
int k;
while(~scanf("%d%d", &k, &MOD)){
VVint A(4, Vint(4));
int B[5] = {0,2,4,6,9};
if(k<5){
printf("%d\n", B[k]%MOD);
continue;
}
A[0][0] = A[0][2] = A[0][3] = 1;
A[1][0] = A[2][1] = A[3][2] = 1;
A = my_pow(A,k-4);
int re = 0;
for(int i=0; i<4; i++)
re = (re + (A[0][i]*B[4-i])%MOD) % MOD;
printf("%d\n", re);
}
return 0;
}
/*
0 1 2 3 4
0 2 4 6 9
----------
0 0
Null
1 2
f m
2 4
ff mm fm mf
3 6
[fff] ffm [fmf] fmm mff mfm mmf mmm
4 9
[ffff] [fffm] [ffmf] ffmm
[fmff] [fmfm] fmmf fmmm
[mfff] mffm [mfmf] mfmm
mmff mmfm mmmf mmmm
5 2^5-17=15
[fffff] [ffffm] [fffmf] [fffmm]
[ffmff] [ffmfm] [ffmmf] ffmmm
[fmfff] [fmffm] [fmfmf] [fmfmm]
fmmff fmmfm fmmmf fmmmm
[mffff] [mfffm] mffmf mffmm
[mfmff] [mfmfm] mfmmf mfmmm
[mmfff] mmffm [mmfmf] mmfmm
mmmff mmmfm mmmmf mmmmm
*/