BZOJ4000: [TJOI2015]棋盘 解题报告

来源:互联网 发布:mac隐藏顶栏图标 编辑:程序博客网 时间:2024/05/01 07:28

题解

Description
这里写图片描述
1<=N<=10^6,1<=M<=6



吐槽

真的不得不吐槽这个题意,本来看数据范围觉得是矩乘,突然发现维护2行状态矩阵时间吃不下,想不到去看题解结果woc题目里给的攻击范围的矩阵第一行是第0行,棋子自己的位置其实是矩阵的第2行

题解

知道题意里说的攻击范围的矩阵3×p指的是0~2行后就没什么好说的了,矩乘
先按状压做,先处理一下状态之间的转移,然后矩乘一下


code:

#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<vector>#include<string>#include<bitset>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#include<algorithm>#define ll long long#define inf 1e9#define ii unsigned intusing namespace std;const ii maxn = 1100000;const ii maxm = 6;struct mat{    ii a[1<<maxm][1<<maxm];}Z,zero,tmp;ii p[3][maxm+1];ii n,m,k,w;bool fv[1<<maxm];mat operator *(mat x,mat y){    mat ret=Z;    ii lk=1<<m;    for(ii i=0;i<lk;i++)    {        for(ii j=0;j<lk;j++)            for(ii l=0;l<lk;l++)            {                ret.a[i][j]+=x.a[i][l]*y.a[l][j];            }    }    return ret;}mat pow(ii pw){    mat ret=zero,st=tmp;    ii now=0,nowt=1;    while(now!=pw)    {        if(pw&nowt)        {            now|=nowt;            ret=ret*st;        }        st=st*st;        nowt<<=1;    }    return ret;}bool judge1(ii x,ii y){    if(x>y)swap(x,y);    if(y-x<=w-k&&p[1][k+y-x]) return false;    if(y-x<=k-1&&p[1][k-y+x]) return false;    return true;}bool judge2(ii x,ii y){    if(x<y)    {        if(y-x<=w-k&&p[2][k+y-x]) return false;        if(y-x<=k-1&&p[0][k-y+x]) return false;        return true;    }    else    {        if(x-y<=w-k&&p[0][k+x-y]) return false;        if(x-y<=k-1&&p[2][k-x+y]) return false;        return true;    }}int main(){    scanf("%u%u%u%u",&n,&m,&w,&k); k++;    for(ii i=0;i<3;i++)         for(ii j=1;j<=w;j++) scanf("%u",&p[i][j]);    for(ii l=0;l<1<<m;l++)    {        bool flag=true;        for(ii i=0;i<m;i++)        if(l&(1<<i))        {            for(ii j=0;j<m;j++)            if(i!=j&&(l&(1<<j)))            {                if(!judge1(i,j)){flag=false;break;}            }            if(!flag)break;        }        fv[l]=flag;    }    for(ii i=0;i<1<<m;i++)    if(fv[i])    {        for(ii j=0;j<1<<m;j++)        if(fv[j])        {            ii flag=1;            for(ii li=0;li<m;li++)            if(i&(1<<li))            {                for(ii lj=0;lj<m;lj++)                if(j&(1<<lj))                    if(!judge2(li,lj)){flag=0;break;}                if(!flag)break;            }            tmp.a[i][j]=flag;        }    }    for(ii i=0;i<1<<m;i++) zero.a[i][i]=1;    mat sta;sta.a[0][0]=1;    mat ret=sta*pow(n+1);    printf("%u\n",ret.a[0][0]);    return 0;}
0 0