【刷题】【状态压缩】涂抹果酱

3种状态,所以自己写三进制,and

#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
int n,m,k,mod=1e6;
bool my_and(int x,int y)
{
    for(int i=1;i<=m;i++)
    {
        if(x%3 == y%3) return true;
        x/=3,y/=3;
    }
    return false;
}
bool check(int x)
{
    int lst=3;
    for(int i=1;i<=m;i++)
    {
        if(lst==x%3) return true;
        lst=x%3,x/=3;
    }
    return false;
}

int cnt,st[60],f[2][60];
void prepare()
{
    int mx=3;
    for(int i=1;i<m;i++) mx*=3;
    for(int i=0;i<mx;i++)
        if(check(i)==false) st[++cnt]=i;
}

int main()
{
    scanf("%d%d",&n,&m);
    prepare();
    scanf("%d",&k);
    int sta=0,x;
    for(int i=1;i<=m;i++)
        scanf("%d",&x),sta=sta*3 + x-1;
    
    int pos;
    for(pos=1;pos<=cnt;pos++)
    if(st[pos]==sta) break;
    for(int i=1;i<=n;i++)
    {
        int nw=i&1,pre=nw^1;
        memset(f[nw],0,sizeof(f[nw]));
        if(i==k)
            if(i!=1)
            {
                for(int j=1;j<=cnt;j++)
                    if(!my_and(sta,st[j])) f[nw][pos]=(f[nw][pos]+f[pre][j])%mod;
            }
            else f[nw][pos]=1;
        else
        {
            if(i==1)
                for(int i=1;i<=cnt;i++)
                    f[nw][i]=1;
            else
            for(int j=1;j<cnt;j++)
                for(int k=j+1;k<=cnt;k++)
                    if(!my_and(st[j],st[k]))
                        f[nw][j]=(f[nw][j]+f[pre][k])%mod,f[nw][k]=(f[nw][k]+f[pre][j])%mod;
        }
    }
    
    int ans=0,ed=n&1;
    for(int i=1;i<=cnt;i++) ans=(ans+f[ed][i])%mod;
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xwww666666/p/11674251.html