题意:
n个人排队,f表示女,m表示男,包含子串‘fmf’和‘fff’的序列为O队列,否则为E队列,有多少个序列为E队列。
n个人排队,f表示女,m表示男,包含子串‘fmf’和‘fff’的序列为O队列,否则为E队列,有多少个序列为E队列。
分析:
矩阵快速幂入门题。
下面引用巨巨解释:
用f(n)表示n个人满足条件的结果,那么如果最后一个人是m的话,那么前n-1个满足条件即可,就是f(n-1);
如果最后一个是f那么这个还无法推出结果,那么往前再考虑一位:那么后三位可能是:mmf, fmf, mff, fff,其中fff和fmf不满足题意所以我们不考虑,但是如果是
mmf的话那么前n-3可以找满足条件的即:f(n-3);如果是mff的话,再往前考虑一位的话只有mmff满足条件即:f(n-4)
所以f(n)=f(n-1)+f(n-3)+f(n-4),递推会跪,可用矩阵快速幂
构造一个矩阵:
#include <cstdio> #include <iostream> #include <cstring> #include <string> #include <cstdlib> #include <algorithm> #include <cmath> #include <vector> #include <set> #include <list> #include <queue> #include <map> #include <stack> using namespace std; #define L(i) i<<1 #define R(i) i<<1|1 #define INF 0x3f3f3f3f #define pi acos(-1.0) #define eps 1e-9 #define maxn 100010 #define MOD 1000000007 int N,n,m; struct Matrix { long long a[22][22]; Matrix() { memset(a,0,sizeof(a)); for(int i = 0; i < N; i++) a[i][i] = 1; } }; Matrix operator*(Matrix A,Matrix B) { Matrix ans; for(int i = 0; i < N; i++) for(int j = 0; j < N; j++) { ans.a[i][j] = 0; for(int k = 0; k < N; k++) ans.a[i][j] += (A.a[i][k] * B.a[k][j])%m; ans.a[i][j] %=m; } return ans; } Matrix Pow(Matrix A,long long n) { Matrix ans; while(n) { if(n % 2) ans = ans * A; n /= 2; A = A * A; } return ans; } long long mod_pow(long long aa,long long bb,long long mod) { long long ans = 1; while(bb) { if(bb&1) ans *= aa; ans %= mod; bb /= 2; aa *= aa; aa %= mod; } return ans; } int main() { int t; //scanf("%d",&t); while(scanf("%d%d",&n,&m) != EOF) { N = 4; if(!n) printf("0\n"); else if(n == 1) printf("%d\n",2%m); else if(n == 2) printf("%d\n",4%m); else if(n == 3) printf("%d\n",6%m); else if(n == 4) printf("%d\n",9%m); else { Matrix A; memset(A.a,0,sizeof(A.a)); A.a[0][0] = 1; A.a[0][2] = 1; A.a[0][3] = 1; A.a[1][0] = 1; A.a[2][1] = 1; A.a[3][2] = 1; A = Pow(A,n-4); long long k = A.a[0][0] * 9 % m + A.a[0][1] * 6 % m + A.a[0][2] * 4 % m + A.a[0][3] * 2 % m; printf("%lld\n",k%m); } } }