专栏文章

恩情故事之 MAX0810 使用画图击落 N=100 构造 n^2 方案

P10871题解参与者 3已保存评论 2

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
2 条
当前快照
1 份
快照标识符
@mip6neye
此快照首次捕获于
2025/12/03 07:01
3 个月前
此快照最后确认于
2025/12/03 07:01
3 个月前
查看原文
野蛮题目,下次别出了,,,
经过手玩,奇数猜测是 n2n^2,偶数是 n22n^2-2(显然这是一个上界)。还可以发现在 nn 小的时候(大的没试过)相当程度地乱放就可以达到这个上界,所以题目留给我们构造的空间非常宽松。
奇数一个想法是 nn+2n\to n+2,可以如下构造(图为 n=3n=3):
从两边没填的两行每次移动两格走到中心,每次调换先左/先右(先上/先下),最终剩下的 3×33\times 3 涂了左上角图形,此时除了这个左上角的已涂色格子加起来没有影响;随便构造(例如代码中 COL)一个方案。
偶数的一种较有规律的填法是在中间四个格子选一个填(如果 n=6n=6 特殊处理,n0(mod4)n\equiv 0\pmod 4 则取 (n/2+1,n/2+1)(n/2+1,n/2+1) 否则 (n/2,n/2)(n/2,n/2))再从右下角填到选择格子的行列,每次把最右列最下行填了,然后递归到子问题。
每次填涂最右列最下行的方法是每次尽量选更靠近右下角的,懒得证明,反正这样确实是可以填完并且 AC 的。
应该是 O(n3)O(n^3) 但是出题人素质高开 2102^{10} 所以就通过了,,,
CPP
#include<bits/stdc++.h>
using namespace std;
const int maxn=1050;
int n,a[1050][1050];
int b[maxn],c[maxn],d[maxn*10],e[maxn*10],B=maxn*5;
inline void Pt(int x,int y){
	cout<<x<<" "<<y<<endl;
	if(n%2==0){
		a[x][y]=2;
		b[x]^=1,c[y]^=1,d[x+y+B]^=1,e[x-y+B]^=1;
	}
}
inline void COL(int x,int y){
	Pt(x+1,y+2);
	Pt(x+2,y+2);
	Pt(x+2,y+1);
	Pt(x+1,y+1);
	Pt(x+2,y);
	Pt(x,y+1);
	Pt(x,y+2);
	Pt(x+1,y);
}
inline void F(int n){
	if(n==4){
		if(a[4][4]!=2)Pt(4,4);
		Pt(2,3);Pt(3,4);Pt(4,1);Pt(4,3);
		Pt(1,4);Pt(2,4);Pt(4,2);Pt(3,3);
		Pt(3,1);Pt(1,2);Pt(2,1);Pt(2,2);
		Pt(1,1);
		return ;
	}
	if(n%4==0){
		Pt(n/2+1,n/2+1);
		for(int i=n;i>n/2;i--){
			for(int j=1;j<=2*i-1-(i==n/2+1);j++){
				int x=-1,y;
				for(int k=i;k>=1;k--){
					if(a[k][i]==0&&(b[k]^c[i]^d[k+i+B]^e[k-i+B])==0){x=k,y=i;break;}
					if(a[i][k]==0&&(b[i]^c[k]^d[k+i+B]^e[i-k+B])==0){x=i,y=k;break;}
				}	
				if(x==-1)exit(2);
				Pt(x,y);
			}
		}
		F(n/2);
	}else if(n!=6){
		Pt(n/2,n/2);
		for(int i=n;i>=n/2;i--){
			for(int j=1;j<=2*i-1-(i==n/2);j++){
				int x=-1,y;
				for(int k=i;k>=1;k--){
					if(a[k][i]==0&&(b[k]^c[i]^d[k+i+B]^e[k-i+B])==0){x=k,y=i;break;}
					if(a[i][k]==0&&(b[i]^c[k]^d[k+i+B]^e[i-k+B])==0){x=i,y=k;break;}
				}	
				Pt(x,y);
			}
		}
		F(n/2-1);
	}else{
		Pt(n/2+1,n/2+1);
		for(int i=n;i>n/2+1;i--){
			for(int j=1;j<=2*i-1;j++){
				int x=-1,y;
				for(int k=i;k>=1;k--){
					if(a[k][i]==0&&(b[k]^c[i]^d[k+i+B]^e[k-i+B])==0){x=k,y=i;break;}
					if(a[i][k]==0&&(b[i]^c[k]^d[k+i+B]^e[i-k+B])==0){x=i,y=k;break;}
				}	
				Pt(x,y);
			}
		}
		F(4);
	}
}
signed main(){
	cin>>n;
	if(n&1){
		cout<<n*n<<endl;
		Pt(1,1);
		for(int i=1;i<n;i+=2){
			int cur=0;
			for(int j=1;j<=i-1;j++){
				if(cur){
					Pt(j,i+1);Pt(j,i+2);Pt(i+2,j);Pt(i+1,j);
				}else{
					Pt(j,i+2);Pt(j,i+1);Pt(i+1,j);Pt(i+2,j);
				}
				cur^=1;
			}
			COL(i,i);
		}
	}else{
		if(n==2){
			cout<<1<<endl<<1<<" "<<1<<endl;
			return 0;
		}
		cout<<n*n-2<<endl;		
		F(n);
	}
	return 0;
}

评论

2 条评论,欢迎与作者交流。

正在加载评论...