题解:CF2255C Even If the World Turns
priority__queue · · 题解
思路
step 1 观察/简化题目
观察每个操作——
- 平移:要求信息表示方式不能存绝对坐标
- 旋转:要求信息表示方式不能基于
n ,x ,y 坐标可轮换/交换 - 翻转/镜像:跟旋转差不多
- 反转所有颜色:这个直接规定黑色为颜色少的那个颜色即可(具体看代码)
step 2 设计信息存储方式
观察题目,发现似乎可以把所有黑色的点的横竖坐标分别作为表示信息的方式。
接下来设计信息存储方式。
由于x,y轴没什么本质区别,因此以下只讨论x轴。
令
考虑加减乘除,发现乘除减都不太行。那就只剩下加了。
以下所有数均在
让
发现稍微有点问题:
对于平移操作,设平移了
如何解决?可以让
对于旋转/翻转操作:
所以最终就是这样的表示方式。
step 3 具体如何操作/实现
我们要交换
当前目标格子为
找到一个横坐标为
值得注意的是,这样的黑格是一定存在的。
::::info[证明]
把每个格点想象成一个图上的节点,边为
如果没有这样的黑格,那么这个图一定是由很多相同长度环组成的,设每个环的长度为
显然有
::::
对于第二次运行,我们就扫一遍网格,找到满足
代码
#include <bits/stdc++.h>
using namespace std;
#define fir first
#define sec second
template <class TT>
using vc=vector<TT>;
void solve1(){
int n;
cin >> n;
vc<vc<char>> a(n, vc<char>(n));
int w=0;
for(int i=0;i < n;i++){
for(int j=0;j < n;j++){
cin >> a[i][j];
if(a[i][j] == '#') w++;
}
}
if(w*2 > n*n){ //处理反转操作
for(int i=0;i < n;i++){
for(int j=0;j < n;j++){
if(a[i][j] == '#') a[i][j]='.';
else a[i][j]='#';
}
}
w=n*n-w;
}
int rx, ry;
cin >> rx >> ry;
rx--;
ry--;
int sx0=0, sy0=0;
for(int i=0;i < n;i++){
for(int j=0;j < n;j++){
if(a[i][j] == '#'){
sx0+=i;
sy0+=j;
}
}
}
for(int i=0;i < n;i++){
for(int j=0;j < n;j++){
if(a[i][j] == '#'){
int xx=((i+w*rx-sx0)%n+n)%n, yy=((j+w*ry-sy0)%n+n)%n;
if((xx == i && yy == j) || a[xx][yy] == '.'){
cout << i+1 << " " << j+1 << " " << xx+1 << " " << yy+1 << "\n";
return;
}
}
}
}
}
void solve2(){
int n;
cin >> n;
vc<vc<char>> a(n, vc<char>(n));
int w=0;
for(int i=0;i < n;i++){
for(int j=0;j < n;j++){
cin >> a[i][j];
if(a[i][j] == '#') w++;
}
}
if(w*2 > n*n){ //处理反转操作
for(int i=0;i < n;i++){
for(int j=0;j < n;j++){
if(a[i][j] == '#') a[i][j]='.';
else a[i][j]='#';
}
}
w=n*n-w;
}
int sx0=0, sy0=0;
for(int i=0;i < n;i++){
for(int j=0;j < n;j++){
if(a[i][j] == '#'){
sx0+=i;
sy0+=j;
}
}
}
for(int i=0;i < n;i++){
for(int j=0;j < n;j++){
if(w*i%n == sx0%n && w*j%n == sy0%n){
cout << i+1 << " " << j+1 << "\n";
return;
}
}
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
string RUN;
cin >> RUN;
if(RUN == "first"){
int T;
cin >> T;
while(T--){
solve1();
}
}
else if(RUN == "second"){
int T;
cin >> T;
while(T--){
solve2();
}
}
}