一串字母,只有f,m,但是子串中不能有fmf ,fff 出现,
记答案为f[n],则易得f[0]=1,f[1]=2,f[2]=4,f[3]=6;f[[4]=9;
当长度为N时,若最后一个字符为M,前N-1个字符没有限制,即为F(N-1);
当最后一个字符串为F的时候,就必须去除最后3个字符是fmf和fff的情况(倒数第二个字符为F、M均有可能会不满
足情况),此时最后3个字符可能为mmf和mff;
当后3个字符为mmf时,前N-3个字符没有限制,即F(N-3);
但是当最后四个字符为mmff时,前N-4个字符无限制,即为F(N-4);
即f[n]=f[n-1]+f[n-3]+f[n-4];
转化为矩阵即为:1 0 1 1 F(N-1) F(N) (即是f[n]=1*f[n-1]+0*f[n-2]+1*f[n-3]+1*f[n-4];)
1 0 0 0 * F(N-2) = F(N-1) (下面为单位矩阵)
0 1 0 0 F(N-3) F(N-2)
0 0 1 0 F(N-4) F(N-3)
矩阵快速幂,如果有多组数据,先写一个 EG ,一个初始的矩阵,每次pow(EG,n)就行,反正一开始就赋初值比较方便。
然后结构体的名称可以换一下,为 matrix ,方便记忆。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int m;
struct node{
ll a[4][4];
};
node EG={
1,0,1,1,
1,0,0,0,
0,1,0,0,
0,0,1,0
};
node mul(node A,node B){
node C;
memset(C.a,0,sizeof(C.a));
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
for (int k = 0; k < 4; k++)
{
C.a[i][j] = (A.a[i][k] * B.a[k][j]%m+C.a[i][j])%m;
}
return C;
}
node pow(node A,int n){
node B;
memset(B.a,0,sizeof(B.a));
for (int i = 0; i < 4; i++)
B.a[i][i] = 1;
while(n){
if (n & 1) B = mul(B,A);
A = mul(A,A);
n >>= 1;
}
return B;
}
int main(){
int n;
node res;
int a[4] = {1,2,4,6};
while(scanf("%d%d",&n,&m) == 2){
if (n == 0){
printf("%d\n",1 % m);
continue;
}
if (n == 1){
printf("%d\n",2 %m);
continue;
}
if (n == 2){
printf("%d\n",4%m);
continue;
}
n -=3;
res = pow(EG,n);
long long ans = 0;
for (int i = 0; i < 4; i++){
ans = (ans + res.a[0][i] * a[3-i]%m)%m;
}
printf("%lld\n",ans);
}
return 0;
}