注意到有可爱的相邻位置小限制,考虑对这个地方进行优化。
我们设 \(f_{i,j,s}\) 表示我们目前已经考虑了前 \(i\) 种数,已经加入了 \(j\) 个数到数列里,\(<i\) 且 \(\ge i-4\) 的数的状态为 \(s\),则有:
\[f_{i,j,s}(\operatorname{popcount}(s)+1)\to f_{i+1,j+1,(2s+1)\&(2^m-1)}
\]
\[f_{i,j,s}\to f_{i+1,j+1,(2s)\&(2^m-1)}
\]
发现 \(j,s\) 长得一脸可以矩阵快速幂优化的样子,所以我们直接一手矩阵快速幂,将时间复杂度从 \(O(nk2^m)\) 优化到 \(O(k^38^m\log n)\)。
#include<bits/stdc++.h>
using namespace std;
const int N=205,p=1e9+7;
int n,k,m,sz,ans;
struct matrix{int a[N][N];}a,b;
matrix operator*(matrix x,matrix y){matrix z;memset(z.a,0,sizeof(z.a));for(int i=0;i<=sz;i++) for(int j=0;j<=sz;j++) for(int d=0;d<=sz;d++)z.a[i][j]=(z.a[i][j]+1ll*x.a[i][d]*y.a[d][j])%p;return z;
}int main(){ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);cin>>n>>k>>m,sz=(k<<m);for(int i=0;i<k;i++) for(int j=0;j<(1<<m);j++){int s=(j<<1)&((1<<m)-1);int cf=1+__builtin_popcount(j);b.a[(i<<m)+j][(i<<m)+s]=1;if(i==k-1) b.a[(i<<m)+j][sz]=cf;else b.a[(i<<m)+j][((i+1)<<m)+s+1]=cf;}b.a[sz][sz]=a.a[0][0]=1;while(n){if(n&1) a=a*b;b=b*b,n>>=1;}return cout<<a.a[0][sz],0;
}