bzoj4000: [TJOI2015]棋盘

难度在题意

状态只有2^6个,预处理出来,再预处理谁可以转移到谁,矩阵快速幂即可

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
typedef unsigned int uint;

int p,k,mp[3];
struct three
{
    int u,g,d;
    three(){} three(int U,int G,int D){u=U,g=G,d=D;}
}sta[110];int top;

struct Matrix
{
    uint mp[110][110];
    friend Matrix operator *(Matrix a,Matrix b)
    {
        Matrix c;
        memset(c.mp,0,sizeof(c.mp));
        for(int i=1;i<=top;i++)
            for(int j=1;j<=top;j++)
                for(int k=1;k<=top;k++)
                    c.mp[i][j]=c.mp[i][j]+a.mp[i][k]*b.mp[k][j];
        return c;
    }
}ans,A;

int main()
{
    int n,m,li;
    scanf("%d%d",&n,&m);li=(1<<m);
    
    int op;
    scanf("%d%d",&p,&k);
    for(int i=0;i<=2;i++)
    {
        for(int j=0;j<p;j++)
        {
            scanf("%d",&op);
            if(op)mp[i]|=(1<<j);
        }
    }
    mp[1]^=(1<<k);
        
    for(int zt=0;zt<li;zt++)
    {
        bool bk=true;
        three t=three(0,0,0);
        for(int j=0;j<m;j++)
            if(zt&(1<<j))
            {
                if(j<k)t.u|=(mp[0]>>k-j)%li;
                else t.u|=(mp[0]<<j-k);
                t.g|=(1<<j);
                if(j<k)t.d|=(mp[2]>>k-j)%li;
                else t.d|=(mp[2]<<j-k);
                
                if(j<k){if(zt&((mp[1]>>k-j)%li)){bk=false;break;}}
                else   {if(zt&(mp[1]<<j-k)){bk=false;break;}}
            }
        if(bk)sta[++top]=t;
    }
    
    for(int i=1;i<=top;i++)
        for(int j=1;j<=top;j++)
            if( !(sta[i].d&sta[j].g) && !(sta[i].g&sta[j].u) )
                A.mp[i][j]=1;
                
    ans.mp[1][1]=1;
    while(n!=0)
    {
        if(n%2==1)ans=ans*A;
        A=A*A;n/=2;
    }
    
    uint uiop=0;
    for(int i=1;i<=top;i++)
        uiop+=ans.mp[1][i];
    printf("%u\n",uiop);
    
    return 0;
}

 

posted @ 2019-03-13 21:15  AKCqhzdy  阅读(102)  评论(0编辑  收藏  举报