8.18模拟:构造

博主分享了在dfs专题考试中的经历,包括T1-T4的解题策略,如构造题tricks、调整法、分类讨论和数学归纳法的应用。重点提到了T2的困难和考场策略的转变。总结中强调了对关键性质把握和新题型适应的重要性。
摘要由CSDN通过智能技术生成

前言

190分
100+0+60+30

明明是dfs专题
不太理想qwq
写了三个dfs就离谱
最不满意的是T2的爆零
其实分类讨论一下是很可做的
而且暴力还因为没开ll挂掉了…
不过毕竟构造题之前几乎没有做过
所以慢慢来吧

收获

一些构造题的trick

  1. 调整法
  2. 数学归纳法
  3. 分类讨论法
  4. 从边界极值等处缩小问题规模法
  5. 乱七八糟法

考场

先看题
数学的石头门困境重新江湖…
似乎就没有啥可做的题

在zld写在前面的难度指引+先写T1的习惯下
先看T1
(到现在似乎说是先看题结果几乎还是顺序做…)
zld果然没有骗我!
想到了把一个2*2的正方形作为基本单位单独处理
每块的最差处理次数也可以证明不超过4次
这样就ok了
但当时就想到这题代码实现可能会有些困难
应该又是道打表搬砖题
但奇怪的道路那题的阴间打表我都写过去了我还怕这个?
所以piapia就开始敲
这题我利用递归转移
自己感觉写的还是非常优美的
只需要一个操作对应的两个表和常规的4宫格tx数组即可
但我因为怕写挂自己造数据和手算输出用了好一段…
9:00

转T2
这什么玩意…
我也有些被zld的难度提示吓到了
觉得这题很可能需要按位考虑贪心的乱七八糟的
然后就越想越迷糊
最后直接开始开心的dfs
试图拿30分走人(伏笔)
9:30

开T3
又是让人没什么想法的题目
有一点直觉本题似乎很可能不会无解
(因为没有多测)
但推来推去也证明不出来
但是第二个30不超过2个讨厌的约束条件倒是推出来必定可行的策略了
然后就写了两个部分分拿60走人
10:10

看T4
又是不知从何推起的神仙题目
搞了半天除了浪费了一堆验算纸一无所获
最后又是dfs了…

复盘

T1

啊这个灯泡我觉得我点的是针不戳
很简洁
所以贴一下码awa

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=105;
const int mod=1e9+7;
int n,m;
int a[N][N];
int tot;
typedef pair<int,int>pr;
pr q[N*N<<2][4];
#define mkp make_pair
int dx[5][5]={{},{0,0,1,1},{0,0,1,1},{0,-1,-1,0},{0,-1,-1,0}};
int dy[5][5]={{},{0,1,0,1},{0,-1,-1,0},{0,0,1,1},{0,-1,0,-1}};
void work(int x,int y,int o){
//	printf("work:x=%d y=%d o=%d\n",x,y,o);
	tot++;
	for(int i=1;i<=3;i++){
//		printf("  xx=%d yy=%d\n",x+dx[o][i],y+dy[o][i]);
		q[tot][i]=mkp(x+dx[o][i],y+dy[o][i]);
		a[x+dx[o][i]][y+dy[o][i]]^=1;
	}
}
int tx[5]={0,0,0,1,1},ty[5]={0,0,1,0,1};
void solve(int x,int y){
	int cnt=a[x][y]+a[x+1][y]+a[x][y+1]+a[x+1][y+1];
//	printf("x=%d y=%d cnt=%d\n",x,y,cnt);
	if(cnt==0) return;
	else if(cnt==1){
		for(int i=1;i<=4;i++){
			int nx=x+tx[i],ny=y+ty[i];
			if(!a[nx][ny]){
				work(x+tx[i],y+ty[i],i);
				solve(x,y);
				return;
			}
		}
	}
	else if(cnt==2){
		for(int i=1;i<=4;i++){
			int nx=x+tx[i],ny=y+ty[i];
			if(a[nx][ny]){
//				printf("nx=%d ny=%d\n",nx,ny);
				work(nx,ny,i);
				solve(x,y);
				return;
			}
		}
	}
	else if(cnt==3){
		for(int i=1;i<=4;i++){
			int nx=x+tx[i],ny=y+ty[i];
			if(!a[nx][ny]){
				work(nx,ny,i);
				solve(x,y);
				return;
			}
		}
	}
	else{
		work(x,y,1);
		solve(x,y);
		return;
	}
}
int main(){
	freopen("bulb.in","r",stdin);
	freopen("bulb.out","w",stdout);
	int t;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n,&m);
		tot=0;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++) scanf("%1d",&a[i][j]);
		}
		if(n%2&&m%2){
			if(a[n][m]) work(n-1,m-1,1);
		}
		if(m%2){
			for(int i=1;i<n;i+=2){
				if(a[i][m]&&a[i+1][m]) work(i,m-1,1);
				else if(a[i][m]) work(i+1,m,4);
				else if(a[i+1][m]) work(i,m,2);
			}
		}
		if(n%2){
			for(int j=1;j<m;j+=2){
				if(a[n][j]&&a[n][j+1]) work(n-1,j,1);
				else if(a[n][j]) work(n,j+1,4);
				else if(a[n][j+1]) work(n,j,3);
			}
		}
		
		for(int i=1;i<=n;i+=2){
			for(int j=1;j<=m;j+=2) solve(i,j);
		}	
		
		printf("%d\n",tot);
		for(int i=1;i<=tot;i++){
			for(int j=1;j<=3;j++) printf("%d %d ",q[i][j].first,q[i][j].second);
			printf("\n");
		}
	}
	return 0;
}
/*
5
2 2
10
11
3 3
011
101
110
4 4
1111
0110
0110
1111
5 5
01011
11001
00010
11011
10000
2 3
011
101

1
4 5
11011
11100
00000
01111
*/

T2

本题的关键性质是
只要从一个偶数往上连续取4个它的异或和就是0了
从一个偶数往上连续数2个就是1
所以分类讨论即可
但k=3和r=l+1且l为奇数的细节有点恶心
感觉可能考场上就是把这个性质想到了想切也没那么容易qwq

T3

调整法
可以证明随着不断调整组内的讨厌关系组数会越来越少
这样就能够证明一直处理下去一定能找到合法解了

T4

数学归纳法
这个东西就是看出来就看出来了…
当时感觉可能会用数学归纳法
但是归纳了半天归纳不出来…
把奇数消掉后变成2n-1的想法是关键

总结

构造毕竟是新题
做的比较少
关键是对关键性质的把握
明天放假了
好耶!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值