P9326 [CCC 2023 S3] Palindromic Poster

题目传送门

我的其他文章

构造+分讨题。调了我两个小时。


1. \(0 < r < n,0 < c < m\)

算是最简单的一种情况了。我们让前 \(c\) 列和前 \(r\) 行都染上同一种字符 a (重叠位置也是 a),其他位置的字符染上另一种字符 b

比如 5 6 3 2 这组数据,最终结果就是这样:

aaaaaa
aaaaaa
aaaaaa
aabbbb
aabbbb

可以发现,除了前 \(r\) 行和前 \(c\) 列(他们显然回文),其他行和列都形如 aa...abb...b,最后一个字符和第一个字符都不是相等的,自然不可能回文。

2. \(r=n,c=m\)

这个也很简单。让所有位置都是字符 \(a\) 就能满足条件。

3. \(r=0,c=0\)

也就是说,我们要想办法构造出一个每一行每一列都不回文的二维字符数组。

这里有一个很简单的构造方法:让 \(a_{i,j}\) 等于第 \(i+j-1 \mod 25\) 个字符即可。这样的话,我们自己模拟一下,建出来的矩阵应该长这样:

abcdefghijklmnopqrstuvwxyabcdefg...
bcdefghijklmnopqrstuvwxyabcdefgh...
cdefghijklmnopqrstuvwxyabcdefghi...
...
yabcdefghijklmnopqrstuvwxyabcdef...
abcdefghijklmnopqrstuvwxyabcdefg...

显然,长这样的矩阵,每行每列都形如 abcdefg...wxyabcdefg...,最后一个字符和第一个字符很大概率不相等,即使相等(假设都是第 \(x\) 个字符),那第二个字符是第 \(x+1\) 个,最后一个字符是第 \(x-1\) 个,也是不相等的。

这样的话,这种情况就搞定了。

可能有人发现了,我们构造出来的矩阵没有 z。不急,这个字符后面有用。

4. \(r=0,c=m\)

我们可以按刚才的构造方法构造出来第一行,第一行就会长这样:

abcdefg...wxyabcdefg...

然后我们让后面的每一行都变成第一行的样子,这个矩阵就形如:

abcdefg...wxyabcdefg...
abcdefg...wxyabcdefg...
abcdefg...wxyabcdefg...
...
abcdefg...wxyabcdefg...
abcdefg...wxyabcdefg...

显然是满足条件的。

5. \(r=n,c=0\)

同理。最终的矩阵长这样:

aaaaaaaa...
bbbbbbbb...
cccccccc...
...
wwwwwwww...
xxxxxxxx...
yyyyyyyy...
aaaaaaaa...
bbbbbbbb...
...

6. \(r=n,0<c<m\)\(c=m,0<r<n\)

这两种情况是同理的。在此只介绍一种情况(\(r=n,0<c<m\))。

首先我们还是按第 3 种情况的方法,先构造出矩阵的前半边。矩阵的后半边呢,我们强制让它回文,也就是让对应位置的字符等于前半边。

如果 \(m\) 是奇数的话构造出来长这样(当然中心点不确定,这里仅为了举例方便):

abcdefg...wxyabcbayxw...gfedcba
bcdefgh...xyabcdcbayx...hgfedcb
...
yabcdef...vwxyabayxwv...fedcday
abcdefg...wxyabcbayxw...gfedcba
bcdefgh...xyabcdcbayx...hgfedcb
...

\(m\) 是偶数则是这样:

abcdefg...wxyabbayxw...gfedcba
bcdefgh...xyabccbayx...hgfedcb
...
yabcdef...vwxyaayxwv...fedcday
abcdefg...wxyabbayxw...gfedcba
bcdefgh...xyabccbayx...hgfedcb
...

这样的话,行全部回文就满足了。同时这样列上没有回文的,方便后面构造。

还记得刚才没有出现的 z 吗?这里我们就要用上它了(虽然它出现在队列里正确性可能也没问题,但是以防万一,总之让它这时候出现在队列正确性一定不会错)

假设我们当前的 \(c\) 是个偶数,那我们让 \([1,\frac c2]\)\([m-\frac c2+1,m]\) 区间里的所有列全部染上颜色 z。容易发现这样对横行没有影响(染完色还是回文的),竖行多了 \(c\) 个回文串,其他串仍然是不回文的。

染完色后大概长这样(假设 \(c=6\)):

zzzdefg...wxyabcbayxw...gfedzzz
zzzefgh...xyabcdcbayx...hgfezzz
...
zzzcdef...vwxyabayxwv...fedczzz
zzzdefg...wxyabcbayxw...gfedzzz
zzzefgh...xyabcdcbayx...hgfezzz
...
zzzdefg...wxyabbayxw...gfedzzz
zzzefgh...xyabccbayx...hgfezzz
...
zzzcdef...vwxyaayxwv...fedczzz
zzzdefg...wxyabbayxw...gfedzzz
zzzefgh...xyabccbayx...hgfezzz
...

如果 \(c\) 是奇数,那么我们还是要分两种情况讨论:\(m\) 是奇数 / 偶数的情况。

\(m\) 是奇数的话,我们就先给矩阵最中间的地方染上 z 的颜色,把 \(c\) 变成偶数后做偶数的染色操作即可。

大概这样(以 \(c=7\) 为例):

zzzdefg...wxyabzbayxw...gfedzzz
zzzefgh...xyabczcbayx...hgfezzz
...
zzzcdef...vwxyazayxwv...fedczzz
zzzdefg...wxyabzbayxw...gfedzzz
zzzefgh...xyabczcbayx...hgfezzz
...

如果 \(m\) 是偶数,那此时是无解的。

证明如下:

如果当前有解的话,一定存在对称的两列 \(x,x'\)\(x'\) 回文但 \(x\) 不回文。但是我们知道所有行都是回文的,所以对于任意行都有 \(a_{i,x}=a_{i,x'}\),所以 \(x\)\(x'\) 列上的字符串应该相等,不会出现一个回文一个不回文的情况。所以此时无解。

\(c=m,0<r<n\) 的情况同理。


综上,我们把所有的情况都讨论完了。接下来看代码:

P9326
#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N=2025;
int n,m,r,c;
char a[N][N];

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin>>n>>m>>r>>c;
	if(r==0&&c==0){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				a[i][j]='a'+(i+j-2)%25;
			}
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				cout<<a[i][j];
			}
			cout<<endl;
		}
	}
	else if(r==0&&c==m){
		for(int j=1;j<=m;j++){
			a[1][j]='a'+(1+j-2)%25;
		}
		for(int i=2;i<=n;i++){
			for(int j=1;j<=m;j++){
				a[i][j]=a[i-1][j];
			}
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				cout<<a[i][j];
			}
			cout<<endl;
		}
	}
	else if(r==n&&c==0){
		for(int i=1;i<=n;i++){
			a[i][1]='a'+(1+i-2)%25;
		}
		for(int j=2;j<=m;j++){
			for(int i=1;i<=n;i++){
				a[i][j]=a[i][j-1];
			}
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				cout<<a[i][j];
			}
			cout<<endl;
		}
	}
	else if(r==n&&c==m){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				cout<<'k';
			}
			cout<<endl;
		}
	}
	else if(r==0){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				a[i][j]='a'+(i+j-2)%25;
			}
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=c;j++){
				a[i][j]='z';
			}
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				cout<<a[i][j];
			}
			cout<<endl;
		}
	}
	else if(c==0){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				a[i][j]='a'+(i+j-2)%25;
			}
		}
		for(int i=1;i<=r;i++){
			for(int j=1;j<=m;j++){
				a[i][j]='z';
			}
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				cout<<a[i][j];
			}
			cout<<endl;
		}
	}
	else if(r<n&&c<m){
		for(int i=1;i<=r;i++){
			for(int j=1;j<=m;j++){
				a[i][j]='w';
			}
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=c;j++){
				a[i][j]='w';
			}
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				if(!a[i][j]) a[i][j]='q';
				cout<<a[i][j];
			}
			cout<<endl;
		}
	} 
	else if(r==n){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=(m+1)/2;j++){
				a[i][j]='a'+(i+j-2)%25;
			}
		}
		if(!(m&1)){
			for(int i=1;i<=n;i++){
				for(int j=m/2+1;j<=m;j++){
					a[i][j]=a[i][m+1-j];
				}
			}
		}
		else{ 
			for(int i=1;i<=n;i++){
				for(int j=m/2+2;j<=m;j++){
					a[i][j]=a[i][m+1-j];
				}
			}
		}
		if((!(m&1))&&((c&1))){//m偶c奇 
			printf("IMPOSSIBLE\n");
			return 0;
		}
		else if((m&1)&&(c&1)){//m奇c奇 
			for(int i=1;i<=n;i++){
				a[i][(m+1)/2]='z';
			}
		}
		for(int j=1;j<=c/2;j++){
			for(int i=1;i<=n;i++){
				a[i][j]='z';
			}
		}
		for(int j=m-c/2+1;j<=m;j++){
			for(int i=1;i<=n;i++){
				a[i][j]='z';
			}
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				cout<<a[i][j];
			}
			cout<<endl;
		}
	}
	else if(c==m){
		for(int j=1;j<=m;j++){
			for(int i=1;i<=(n+1)/2;i++){
				a[i][j]='a'+(i+j-2)%25;
			}
		}
		if(!(n&1)){
			for(int j=1;j<=m;j++){
				for(int i=n/2+1;i<=n;i++){
					a[i][j]=a[n+1-i][j];
				}
			}
		}
		else{
			for(int i=n/2+2;i<=n;i++){
				for(int j=1;j<=m;j++){
					a[i][j]=a[n+1-i][j];
				}
			}
		}
		if((!(n&1))&&((r&1))){//n偶r奇 
			printf("IMPOSSIBLE\n");
			return 0;
		}
		else if(((n&1))&&((r&1))){//n奇r奇 
			for(int j=1;j<=m;j++){
				a[(n+1)/2][j]='z';
			}
		}
		for(int j=1;j<=m;j++){
			for(int i=1;i<=r/2;i++){
				a[i][j]='z';
			}
		}
		for(int j=1;j<=m;j++){
			for(int i=n-r/2+1;i<=n;i++){
				a[i][j]='z';
			}
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				cout<<a[i][j];
			}
			cout<<endl;
		}
	}
	return 0;
}
posted @ 2025-11-15 16:06  qwqSW  阅读(4)  评论(0)    收藏  举报