首页 > 其他 > 详细

Luogu3977 [TJOI2015]棋盘

时间:2020-07-30 22:05:55      阅读:137      评论:0      收藏:0      [点我收藏+]

Description

link

给定一个大小为 \(n \times m\) 的棋盘,同时给定一个棋子的攻击范围的情况,是一个 \(3 \times p\) 的矩阵

要求放置棋子的方案数

\(p \le m ,n\le 10^6,m\le 6\)

Solution

这真的是阅读理解题,请仔细分析 \(0/1\) 后判断每个棋子的攻击范围

然后状压这部分就是一个考验代码能力的部分……(比如我写了俩小时,旁边的 \(@happyguy\) 就写了半小时……)

然后这样并不能通过本题,毕竟复杂度在那里……

然后我们发现这个转移是有向的……(这部分抄了题解……毕竟不会矩阵加速)

两个状态之间就是两个状态之间的指向性转移

然后建立初始矩阵,快速幂

Code

#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();}

Luogu3977 [TJOI2015]棋盘

原文:https://www.cnblogs.com/yspm/p/13406623.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!