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; }