记 dp[i] 为长度 i 且符合题意的方案数,dp[n]就是解
符合方案的是不含 fmf 和 fff 子串的字符串
考虑如何从前面几项递推出后面第 i 项
(★表示存在生成的非法方案)←其实没啥用处
i=1 时
m③ f③
i=2 时
mm② mf② fm★② ff★②
i=3 时
mmm mmf mfm★ mff★ fmm ffm★
i=4 时
mmmm① mmmf① mmfm★① mmff★① mfmm① mffm★① fmmm① fmmf① ffmm①
i=5 时
mmmmm① mmmmf② mmmfm① mmmff③ mmfmm① mmffm① mfmmm① mfmmf② mffmm① fmmmm① fmmmf② fmmfm① fmmff③ ffmmm① ffmmf②
i=5 时,考虑第 i-1 项,其中所有方案接 m 都可以转移①
考虑第 i-2 项,只可以接_f 形式,由★可得出无论是 mf 还是 ff 都有非法方案存在的结论,无法转移
考虑第 i-3 项,可以接__f 形式 mmf 可以②,mff 非法,f_f 非法
考虑第 i-4 项,只剩下 mmff 形式③
所有生成的第五项的串全部转移完毕,得到 dp(n)=dp(n-1)+dp(n-3)+dp(n-4)
/*H E A D*/
int MOD = 9973;
inline ll mod(ll a){return a%MOD;}
struct Matrix{
ll mt[22][22],r,c;
void init(int rr,int cc,bool flag=0){
r=rr;c=cc;
memset(mt,0,sizeof mt);
if(flag) rep(i,1,r) mt[i][i]=1;
}
Matrix operator * (const Matrix &rhs)const{
Matrix ans; ans.init(r,rhs.c);
rep(i,1,r){
rep(j,1,rhs.c){
int t=max(r,rhs.c);
rep(k,1,t){
ans.mt[i][j]+=mod(mt[i][k]*rhs.mt[k][j]);
ans.mt[i][j]=mod(ans.mt[i][j]);
}
}
}
return ans;
}
};
Matrix fpw(Matrix A,int n){
Matrix ans;ans.init(A.r,A.c,1);
while(n){
if(n&1) ans=ans*A;
n>>=1;
A=A*A;
}
return ans;
}
int bas[5][5]={
{0,0,0,0,0},
{0,1,0,1,1},
{0,1,0,0,0},
{0,0,1,0,0},
{0,0,0,1,0},
};
int bas2[5]={0,9,6,4,2};
int main(){
int n,m;
Matrix A;A.init(4,4);
rep(i,1,4) rep(j,1,4) A.mt[i][j]=bas[i][j];
Matrix b; b.init(4,1);
rep(i,1,4) b.mt[i][1]=bas2[i];
while(cin>>n>>m){
MOD=m;
if(n<=3){
println(b.mt[5-n][1]%MOD);
continue;
}
Matrix res=fpw(A,n-4); res=res*b;
ll ans=mod(res.mt[1][1]+m);
println(ans);
}
return 0;
}
解法二:
很显然不断拼接枚举简直累死人,干嘛不直接把三位的子串全部递推出来
注意 fmf 和 fff 递推时强制设 0 表示非法方案
保险起见还是设递推项为第五项开始
时间复杂度较高,不过依然能 AC
/*H E A D*/
int MOD = 9973;
inline ll read(){
ll x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline ll mod(ll a){return a%MOD;}
struct Matrix{
ll mt[22][22],r,c;
void init(int rr,int cc,bool flag=0){
r=rr;c=cc;
memset(mt,0,sizeof mt);
if(flag) rep(i,1,r) mt[i][i]=1;
}
Matrix operator * (const Matrix &rhs)const{
Matrix ans; ans.init(r,rhs.c);
rep(i,1,r){
rep(j,1,rhs.c){
int t=max(r,rhs.c);
rep(k,1,t){
ans.mt[i][j]+=mod(mt[i][k]*rhs.mt[k][j]);
ans.mt[i][j]=mod(ans.mt[i][j]);
}
}
}
return ans;
}
};
Matrix fpw(Matrix A,int n){
Matrix ans;ans.init(A.r,A.c,1);
while(n){
if(n&1) ans=ans*A;
n>>=1;
A=A*A;
}
return ans;
}
// 4 7 -> 9->O fff_(m|f) fmf_(m|f) fff fmf
//dp[1][i]:fff dp[1][i+1]=0dp[1][i]+0dp[2][i] 0
//dp[2][i]:mff dp[2][i+1]=dp[3][i]+dp[5][i] 2
//dp[3][i]:fmf dp[3][i+1]=0dp[4][i]+0dp[6][i] 0
//dp[4][i]:ffm dp[4][i+1]=dp[1][i]+dp[2][i] 1
//dp[5][i]:mmf dp[5][i+1]=dp[7][i]+dp[8][i] 4
//dp[6][i]:mfm dp[6][i+1]=dp[3][i]+dp[5][i] 2
//dp[7][i]:fmm dp[7][i+1]=dp[4][i]+dp[6][i] 2
//dp[8][i]:mmm dp[8][i+1]=dp[7][i]+dp[8][i] 4
int bas[9][9]={
{0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0},
{0,0,0,1,0,1,0,0,0},
{0,0,0,0,0,0,0,0,0},
{0,1,1,0,0,0,0,0,0},
{0,0,0,0,0,0,0,1,1},
{0,0,0,1,0,1,0,0,0},
{0,0,0,0,1,0,1,0,0},
{0,0,0,0,0,0,0,1,1},
};
int bas2[9]={0,0,2,0,1,4,2,2,4};
int main(){
int n,m;
Matrix A;A.init(8,8);
rep(i,1,8) rep(j,1,8) A.mt[i][j]=bas[i][j];
Matrix b; b.init(8,1);
rep(i,1,8) b.mt[i][1]=bas2[i];
while(cin>>n>>m){
MOD=m;
if(n<=4){
switch(n){
case 0 :println(0%MOD);break;
case 1 :println(2%MOD);break;
case 2 :println(4%MOD);break;
case 3 :println(6%MOD);break;
case 4 :println(9%MOD);break;
}
continue;
}
Matrix res=fpw(A,n-5); res=res*b;
ll ans=0;
// rep(i,1,8) cout<<res.mt[i][1]<<" ";cout<<endl;
rep(i,1,8) ans=mod(ans+res.mt[i][1]+m);
println(ans);
}
return 0;
}