题目链接:https://loj.ac/problem/10172
解题思路
就和国王问题一样,只不过国王是二进制,这题需要转化为三进制,然后从k往前dp,再从k往后dp,两个方案数相乘即是答案。
AC代码
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll mod=1e6;
const int maxn=1e4+5;
ll dp[maxn][250];
int mp[6];
int n,m,k,cnt;
int sta;
int st[250];
bool check(int a)
{
int tmp=-1,last=-1;
for(int i=1;i<=m;++i)
{
tmp=a%3;
if(tmp==last)
return false;
last=tmp;
a/=3;
}
return true;
}
int quickpow(int a,int b)
{
int res=1;
while(b)
{
if(b&1)
res=res*a;
b>>=1;
a=a*a;
}
return res;
}
bool judge(int a,int b)
{
for(int i=1;i<=m;++i)
{
if(a%3==b%3)
return false;
a/=3;
b/=3;
}
return true;
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;++i)
{
scanf("%d",&mp[i]);
sta=sta*3+mp[i]-1;
}
int maxx=quickpow(3,m);
for(int i=0;i<maxx;++i)
{
if(check(i))
st[++cnt]=i;
}
int pos=-1;
for(int i=1;i<=cnt;++i)
{
if(st[i]==sta)
{
pos=i;
break;
}
}
if(pos==-1)
{
puts("0");
return 0;
}
dp[k][pos]=1;
for(int i=k-1;i>=1;i--)
for(int j=1;j<=cnt;++j)
for(int k=1;k<=cnt;++k)
{
if(judge(st[j],st[k]))
dp[i][j]=(dp[i][j]+dp[i+1][k])%mod;
}
for(int i=k+1;i<=n;++i)
for(int j=1;j<=cnt;++j)
for(int k=1;k<=cnt;++k)
{
if(judge(st[j],st[k]))
dp[i][j]=(dp[i][j]+dp[i-1][k])%mod;
}
ll ans1=0,ans2=0;
for(int i=1;i<=cnt;++i)
ans1=(ans1+dp[1][i])%mod;
for(int i=1;i<=cnt;++i)
ans2=(ans2+dp[n][i])%mod;
if(k==1)
printf("%lld\n",ans2);
else if(k==n)
printf("%lld\n",ans1);
else
printf("%lld\n",ans1*ans2%mod);
return 0;
}