给定一个大小为 \(n \times m\) 的棋盘,同时给定一个棋子的攻击范围的情况,是一个 \(3 \times p\) 的矩阵
要求放置棋子的方案数
\(p \le m ,n\le 10^6,m\le 6\)
这真的是阅读理解题,请仔细分析 \(0/1\) 后判断每个棋子的攻击范围
然后状压这部分就是一个考验代码能力的部分……(比如我写了俩小时,旁边的 \(@happyguy\) 就写了半小时……)
然后这样并不能通过本题,毕竟复杂度在那里……
然后我们发现这个转移是有向的……(这部分抄了题解……毕竟不会矩阵加速)
两个状态之间就是两个状态之间的指向性转移
然后建立初始矩阵,快速幂
#include<bits/stdc++.h>
using namespace std;
namespace yspm{
inline int read()
{
int res=0,f=1; char k;
while(!isdigit(k=getchar())) if(k==‘-‘) f=-1;
while(isdigit(k)) res=res*10+k-‘0‘,k=getchar();
return res*f;
}
const int N=1e6+10;
bool vis[4][10],abl[100],t1[100][100],t2[100][100];
int n,m,k,p,s;
#define ui unsigned int
struct node{
ui a[100][100];
ui* operator[](int x){return a[x];}
inline void init(){memset(a,0,sizeof(a)); return ;}
inline void work(){for(int i=0;i<=s;++i) a[i][i]=1; return ;}
}b,a;
inline node mul(node a,node b)
{
node res; res.init();
for(int i=0;i<=s;++i)
{
for(int j=0;j<=s;++j)
{
for(int k=0;k<=s;++k) res[i][j]+=a[i][k]*b[k][j];
}
}
return res;
}
inline bool judge1(int x,int y)
{
if(!abl[x]||!abl[y]) return 0;
for(int i=1;i<=m;++i)
{
if(!(x&(1<<(i-1)))) continue;
int t=i-k;
for(int j=1;j<=m;++j)
{
if(j+t<1) continue;
if(j+t>m) continue;
if(!vis[3][j]) continue;
if(y&(1<<(j+t-1))) return 0;
}
}
return 1;
}
inline bool judge2(int x,int y)
{
if(!abl[x]||!abl[y]) return 0;
for(int i=1;i<=m;++i)
{
if(!(x&(1<<(i-1)))) continue;
int t=i-k;
for(int j=1;j<=m;++j)
{
if(j+t<1) continue;
if(j+t>m) continue;
if(!vis[1][j]) continue;
if(y&(1<<(j+t-1))) return 0;
}
}
return 1;
}
inline bool c1(int x)
{
for(int i=1;i<=m;++i)
{
if(!(x&(1<<(i-1)))) continue;
int t=i-k;
for(int j=1;j<=p;++j)
{
if(!vis[2][j]) continue;
if(j+t<1) continue;
if(j+t>m) continue;
if(x&(1<<(j+t-1))) return 0;
}
} return 1;
}
signed main()
{
n=read(); m=read(); p=read(); k=read()+1;
for(int i=1;i<=3;++i)
{
for(int j=1;j<=p;++j) vis[i][j]=read();
} vis[2][k]=0;
s=(1<<m)-1;
for(int i=0;i<=s;++i) abl[i]=c1(i);
for(int i=0;i<=s;++i)
{
for(int j=0;j<=s;++j) t1[i][j]=judge1(i,j);
}
for(int i=0;i<=s;++i)
{
for(int j=0;j<=s;++j) t2[i][j]=judge2(i,j);
}
for(int j=0;j<=s;++j)
{
for(int k=0;k<=s;++k)
{
if(t1[j][k]&&t2[k][j]) b[j][k]++;
}
}
a=b; --n; for(;n;n>>=1,a=mul(a,a)) if(n&1) b=mul(b,a);
ui ans=0; for(int i=0;i<=s;++i) ans+=b[n][i]; cout<<ans<<endl;
return 0;
}
}
signed main(){return yspm::main();}
原文:https://www.cnblogs.com/yspm/p/13406623.html