逗比题面,毁我青春
行列编号从零开始。。。然后我以为那个点在最上面那排。。。
妈蛋那样要记两排状态!!!
点在中间那排的话记一排状态矩乘转移就行了。
#include <bits/stdc++.h>
using namespace std;
#define ui unsigned int
int n,m,p,K;
int a[4][7],able[71];
ui ans;
struct Matrix
{
ui w[71][71];
void init()
{
memset(w,0,sizeof(w));
for(int i=0;i<1<<m;i++)w[i][i]=1;
}
}mat,tmp;
int poss(int x,int y)
{
if(K+y<0||K+y>=p)return 0;
return a[1+x][K+y];
}
void mul(Matrix &r1,Matrix &r2,Matrix &r3)
{
memset(&tmp,0,sizeof(tmp));
for(int k=0;k<1<<m;k++)
for(int i=0;i<1<<m;i++)if(r2.w[i][k])
for(int j=0;j<1<<m;j++)if(r3.w[k][j])
tmp.w[i][j]=tmp.w[i][j]+r2.w[i][k]*r3.w[k][j];
memcpy(r1.w,tmp.w,sizeof(r1.w));
}
Matrix qpow(Matrix x,int y)
{
Matrix ret;ret.init();
while(y)
{
if(y&1)mul(ret,ret,x);
mul(x,x,x);y>>=1;
}
return ret;
}
int main()
{
//freopen("tt.in","r",stdin);
scanf("%d%d%d%d",&n,&m,&p,&K);
for(int i=0;i<3;i++)
for(int j=0;j<p;j++)
scanf("%d",&a[i][j]);
for(int i=0;i<1<<m;i++)
{
able[i]=1;
for(int j=0;j<m;j++)if(i>>j&1)
for(int k=0;k<m;k++)if((i>>k&1)&&k!=j)
if(poss(0,k-j))able[i]=0;
}
for(int i=0;i<1<<m;i++)if(able[i])
for(int j=0;j<1<<m;j++)if(able[j])
{
mat.w[i][j]=1;
for(int k=0;k<m;k++)if(i>>k&1)
for(int u=0;u<m;u++)if(j>>u&1)
if(poss(1,u-k)||poss(-1,k-u))
mat.w[i][j]=0;
}
mat=qpow(mat,n);
for(int i=0;i<1<<m;i++)
ans+=mat.w[0][i];
printf("%u\n",ans);
return 0;
}

本文介绍了一种使用矩阵快速幂解决特定类型问题的方法,并通过一个具体的编程实例详细展示了如何实现这一算法。文中涉及状态压缩、矩阵乘法及快速幂运算等关键技术点。
3880

被折叠的 条评论
为什么被折叠?



