k 太小了,结合题目易于想到枚举前 2^k 位的状态,然后限制不是一般算法能做的,考虑 \texttt{dp} ,每加一位贡献只跟前 k-1 位有关,设进状态转移,设 f_{i,j} 表示考虑到第 i 位,后 k-1 位状态为 j 的方案数,每次转移分别考虑 j 新加一位 0 或 1 是否合法就行,O(2^{2^k+k-1}n)。
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const ll mod=998244353;
int n,k;
ll f[501][11];
ll ans;
int rev(int x){
int res=0;
for(int i=0;i<k;++i)
res|=(((x>>(k-1-i))&1)<<i);
return res;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>k;
for(int s=0;s<(1<<(1<<k));++s){
#define chk(s,x) (s&(1<<(rev(x))))
bool fl=0;
//判一下枚举的 s 合不合法
for(int i=0,tmp=s%(1<<k-1);i+k-1<(1<<k);++i){
tmp|=(((s>>(i+k-1))&1)<<k-1);
if(!chk(s,tmp)){
fl=1;
break;
}
tmp>>=1;
}
if(fl)continue;
memset(f,0,sizeof f);
f[(1<<k)-1][s>>((1<<k)-k+1)]=1;
for(int i=(1<<k)-1;i<n-1;++i){
for(int j=0;j<(1<<k-1);++j){
if(!f[i][j])continue;
if(chk(s,j))(f[i+1][j>>1]+=f[i][j])%=mod;
if(chk(s,j|(1<<k-1)))(f[i+1][(j|(1<<k-1))>>1]+=f[i][j])%=mod;
}
}
for(int i=0;i<(1<<k-1);++i){
(ans+=f[n-1][i])%=mod;
}
}
cout<<ans;
return 0;
}