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; }
pain and happy in the cruel world.