Member Single Round Match 494 Round 1 - Division I, Level Three KnightsOut题解

首先对于这一类题目时存在一个 O ( ( n m ) 3 ) O((nm)^3) O((nm)3)的暴力的。
假设每一个格子是一个变量,1表示选中,0则没有。
根据题意可以列出若干个异或方程组,要求每一个格子异或出来都要等于1。高斯消元可以在 O ( ( n m ) 3 ) O((nm)^3) O((nm)3)内做出,答案则是 2 自 由 元 个 数 2^{自由元个数} 2
然后考虑以下的问题:

有一个n*m 的网格,每一个格子最初时白色,你每一次选中一个格子,将它和它的四个邻居(如果存在的话)全部颜色反转,找到一种方案。

显然,如果n/m比较小时可以暴力枚举第一行/第一列。然后往后的每一行/每一列,根据前面的那一格而定。也就是说第一行确定,下面的所有点的方案也就确定了。这样可以做到 O ( 2 n ∗ m ) O(2^n*m) O(2nm)虽然这个暴力远不如高斯消元的 O ( ( n ∗ m ) 3 ) O((n*m)^3) O((nm)3)但我们可以从中获得启发。
其实这个问题也有这样的性质,如果从上往下从左往右的选择,如果当前的格子为 ( i , j ) (i,j) (i,j),则当且仅当 ( i − 2 , j − 1 ) = 0 (i-2,j-1)=0 (i2,j1)=0时才选择(i,j)。
这样我们就可以搞出每一个格子是否选择与前两行和第一列中格子的关系。
因为如果一个格子 ( i , j ) (i,j) (i,j)存在一个格子 ( i + 2 , j + 1 ) (i+2,j+1) (i+2,j+1) ( i , j ) (i,j) (i,j)一定是黑色。所以只需要考虑没有这些点的格子。也就是最后两行和最后一列。
用之前算出的关系来列方程可以做到 O ( ( n + m ) 3 + n ∗ m ∗ ( n + m ) / 64 ) O((n+m)^3+n*m*(n+m)/64) O((n+m)3+nm(n+m)/64)
code:

/*
{

AuThOr Gwj
*/
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define R(a) cin>>a
#define R2(a,b) cin>>a>>b
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
const int MAXN=155;
const int MOD=123456789;
typedef pair<bool,bitset<MAXN*3> > data ;
data inf[MAXN][MAXN];
int n,m;
int dire[8][2]={{1,2},{1,-2},{-1,2},{-1,-2},{2,1},{-2,1},{2,-1},{-2,-1}};
bool equ[550][550];
int Gauss(){
	int rest=0;
	int las=1;
//	rb(i,1,)
	rb(j,1,m-1){
		bool ok=0;
		rb(i,las,n){
			if(equ[i][j]){
				ok=1;
				swap(equ[las++],equ[i]);
				break;
			}
		}
		if(!ok){
			rest++;
			continue;
		}
		rb(i,1,n){
			if(las-1==i) continue;
			if(!equ[i][j]) continue;
			rb(k,1,m)
				equ[i][k]^=equ[las-1][k];
		}
	}
	rb(i,las,n)
	if(equ[i][m]) rest=-1;
	return rest;
}
int id[1000000],id2[1000000];
class KnightsOut{
	public: 
	int count(int N, int M){
		int rest=0;
		int res=1;
		if(N*M<=500){
			n=m=N*M;
			rb(i,1,N)
				rb(j,1,M){
					int ni,nj;
					rep(k,8){
						ni=i+dire[k][0];
						nj=j+dire[k][1];
						if(ni>=1&&ni<=N&&nj>=1&&nj<=M){
							equ[(ni-1)*M+nj][(i-1)*M+j]=1;
						}
					}
					equ[(i-1)*M+j][(i-1)*M+j]=1;
				}
			m++;
			rb(i,1,n)
				equ[i][m]=1;
			rest=Gauss();
		}
		else{
			int cnt=0;
			rb(i,1,2)
				rb(j,1,M){
					id[(i-1)*M+j]=++cnt;	
				}  
			rb(i,3,N)
				id[(i-1)*M+1]=++cnt;
			rb(i,1,2)
				rb(j,1,M){
					inf[i][j].FIR=0;
					inf[i][j].SEC.set(id[(i-1)*M+j]);	
				}
			rb(i,3,N)
				inf[i][1].FIR=0,inf[i][1].SEC.set(id[(i-1)*M+1]);
			rb(i,1,N)
				rb(j,1,M){
					if(i<=2) continue;
					if(j==1) continue;
					int li,lj;
					li=i-2;
					lj=j-1;
					inf[i][j].FIR=1;
					rep(k,8){
						int ni,nj;
						ni=li+dire[k][0];
						nj=lj+dire[k][1];
						if(ni==i&&nj==j) continue;
						if(ni<1||ni>N||nj<1||nj>M) continue;
						inf[i][j].FIR^=inf[ni][nj].FIR;
						inf[i][j].SEC^=inf[ni][nj].SEC;
					}
					inf[i][j].FIR^=inf[li][lj].FIR;
					inf[i][j].SEC^=inf[li][lj].SEC;
				}
			m=cnt;
			rb(i,N-1,N)
				rb(j,1,M)
				{
					n++;
					bitset<MAXN*3> bbs;
					bool fli=0;
					bbs=inf[i][j].SEC;
					fli=inf[i][j].FIR;
					rep(k,8)
					{
						int ni,nj;
						ni=dire[k][0]+i;
						nj=dire[k][1]+j;
						if(ni>=1&&ni<=N&&nj>=1&&nj<=M){
							bbs^=inf[ni][nj].SEC;
							fli^=inf[ni][nj].FIR;
						}
					}	
					rb(k,1,cnt)
						if(bbs[k]){
							equ[n][k]=1;
						}
					if(!fli){
						equ[n][m+1]=1;
					}	
				}
			rb(i,1,N-2)
			{
				n++;
				bitset<MAXN*3> bbs;
				bool fli=0;
					bbs=inf[i][M].SEC;
					fli=inf[i][M].FIR;
					rep(k,8)
					{
						int ni,nj;
						ni=dire[k][0]+i;
						nj=dire[k][1]+M;
						if(ni>=1&&ni<=N&&nj>=1&&nj<=M){
							bbs^=inf[ni][nj].SEC;
							fli^=inf[ni][nj].FIR;
						}
					}	
					rb(k,1,cnt)
						if(bbs[k]){
							equ[n][k]=1;
						}
					if(!fli){
						equ[n][m+1]=1;
					}	
			}
			m++;
//			cout<<n<<" "<<m<<endl;
			rest=Gauss();
//			cout<<rest<<endl;
		}
		if(rest==-1) res=0;
		else
		rb(i,1,rest)
			res<<=1,res%=MOD;
		return res;
	}
};
//KnightsOut solver;
//int main(){
//	fastio;
//	cout<<solver.count( 	
//69,
//142
//)<<endl;
//	return 0;
//}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值