爆搜出三进制的状态,因为m<=5,所以状态最多为3*(2^5)=48个,然后就可以用一个二维dp来统计答案了。
可以发现给出行上和给出行下的方案数是一样的,设给出行上的方案数为ans1,给出行下的方案数为ans2,答案即为 ans1*ans2。
所以严格意义上不算是状压dp吧,没有用到二进制状压的精髓。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e4+5,M=50,MOD=1e6;
int n,m,k,cnt,ans1,ans2,ans,id;
int a[M],f[N][M];
bool pd[M][M];
struct number{int a[M];}num[M];
void dfs(int x,int last)
{
if (x==m+1)
{
cnt++;
for (register int i=1; i<=m; ++i) num[cnt].a[i]=a[i];
return;
}
for (register int i=1; i<=3; ++i)
if (i!=last)
{
a[x]=i;
dfs(x+1,i);
}
}
signed main(){
scanf("%lld%lld",&n,&m);
dfs(1,-1);
scanf("%lld",&k);
for (register int i=1; i<=m; ++i) scanf("%lld",&a[i]);
for (register int i=1; i<m; ++i) if (a[i]==a[i+1]) {printf("%lld\n",0ll); return 0;}
for (register int i=1; i<cnt; ++i)
for (register int j=i+1; j<=cnt; ++j)
{
bool jay=true;
for (register int k=1; k<=m; ++k) if (num[i].a[k]==num[j].a[k]) {jay=false; break;}
pd[i][j]=pd[j][i]=jay;
}
for (register int i=1; i<=cnt; ++i)
{
bool jay=true;
for (register int j=1; j<=m; ++j) if (a[j]!=num[i].a[j]) {jay=false; break;}
if (jay) {id=i; break;}
}
f[k][id]=1;
for (register int i=1; i<=cnt; ++i) if (pd[i][id]) f[k+1][i]=1;
for (register int i=k+2; i<=n; ++i)
for (register int j=1; j<=cnt; ++j)
for (register int k=1; k<=cnt; ++k) if (pd[j][k]) f[i][j]=(f[i][j]+f[i-1][k])%MOD;
for (register int i=1; i<=cnt; ++i) if (pd[i][id]) f[k-1][i]=1;
for (register int i=k-2; i>=1; --i)
for (register int j=1; j<=cnt; ++j)
for (register int k=1; k<=cnt; ++k) if (pd[j][k]) f[i][j]=(f[i][j]+f[i+1][k])%MOD;
for (register int i=1; i<=cnt; ++i) ans1=(ans1+f[1][i])%MOD;
for (register int i=1; i<=cnt; ++i) ans2=(ans2+f[n][i])%MOD;
ans=(ans1*ans2)%MOD;
printf("%lld\n",ans);
return 0;
}