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;
}

浙公网安备 33010602011771号