Official

B - Enlarged Checker Board Editorial by m_99


はじめに

本解説では行や列等の番号を0-indexedで扱います。たとえば、左上のタイルはタイル \((0,0)\) となります。

基本方針

次の2つの問題を考えます。

  1. マス目 \(X\) のタイル \((i,j)\) の色は何か
  2. マス目 \(X\) の上から \(i\) 行目、左から \(j\) 列目のマス(以降マス \((i,j)\) とする)が属するタイル \((i',j')\) はどこか

この2つの問題が解ければ、各 \(i,j\) に対してマス \((i,j)\) が属するタイル \((i',j')\) が白いならマス \((i,j)\) は白、黒いなら黒とすることでマス目 \(X\) を求めることが出来ます。

タイル \((i,j)\) の色は何かを求める

\(X\) の各タイルは、\(0\) 行目は左から白、黒、白、…と交互に、\(1\) 行目は黒、白、黒、…と交互に、\(2\) 行目は白、黒、白、…と交互になっています。より一般に、\(i\) 行目のタイルは \(i\) が偶数のときは白から始めて交互に、奇数のときは黒から始めて交互に白と黒が並んでいます。
白、黒、白、…と並んでいる行において、 \(j\) 列目は \(j\) が偶数のときは白で奇数のときは黒です。左端が黒の場合はその逆です。
ここまでの議論に基づいて各タイルの色を求めるC++のコードを以下に示します。

vector<string> tiles(N,string(N,'-'));
for(int i=0;i<N;i++){
	if(i%2==0){
		for(int j=0;j<N;j++){
			if(j%2==0)tiles[i][j] = '.';
			else tiles[i][j] = '#';
		}
	}
	else{
		for(int j=0;j<N;j++){
			if(j%2==0)tiles[i][j] = '#';
			else tiles[i][j] = '.';
		}
	}
}

あるいは、\(i+j\) が偶数ならばタイル \((i,j)\) は白、奇数ならば黒、という特徴付けをすることもできます。

マス \((i,j)\) が属するタイル \((i',j')\) を求める

各タイルが \(A\)\(B\) 列のマス目であることを考えると、たとえばタイル \((0,0)\) には行が \(0\) 以上 \(A\) 未満で列が \(0\) 以上 \(B\) 未満のマス目が含まれます。これを一般化すると、領域 \((i',j')\) には \(A \times i' \leq i \lt A \times (i'+1)\) かつ \(B \times j' \leq j \lt B \times (j'+1)\) を満たすマス \((i,j)\) が含まれるといえます。逆に、マス \((i,j)\) が属する領域 \((i',j') \)\(i'= \lfloor \frac{i}{A} \rfloor, j'= \lfloor \frac{j}{B} \rfloor \) として求めることが出来ます。

初めに述べた通り、こうして求めた \((i',j')\) に対して タイル \((i',j')\) の色を参照することで \(X\) の各マスの色を求めることが出来ます。よって本問を解くことが出来ました。

実装例1

#include <bits/stdc++.h>
using namespace std;

int main() {
    
	int N,A,B;
	cin>>N>>A>>B;
	
	vector<string> tiles(N,string(N,'-'));
	for(int i=0;i<N;i++){
		if(i%2==0){
			for(int j=0;j<N;j++){
				if(j%2==0)tiles[i][j] = '.';
				else tiles[i][j] = '#';
			}
		}
		else{
			for(int j=0;j<N;j++){
				if(j%2==0)tiles[i][j] = '#';
				else tiles[i][j] = '.';
			}
		}
	}
	
	vector<string> X(A*N,string(B*N,'-'));
	for(int i=0;i<A*N;i++){
		for(int j=0;j<B*N;j++){
			X[i][j] = tiles[i/A][j/B];
		}
	}
	
	for(int i=0;i<A*N;i++){
		cout<<X[i]<<endl;
	}
	
    return 0;
}

実装例2 (\(i+j\) の偶奇を用いて各タイルの色を判定)

#include <bits/stdc++.h>
using namespace std;

int main() {
    
	int N,A,B;
	cin>>N>>A>>B;
	
	vector<string> X(A*N,string(B*N,'-'));
	for(int i=0;i<A*N;i++){
		for(int j=0;j<B*N;j++){
			if(((i/A)+(j/B))%2==0)X[i][j] = '.';
			else X[i][j] = '#';
		}
	}
	
	for(int i=0;i<A*N;i++){
		cout<<X[i]<<endl;
	}
	
    return 0;
}

posted:
last update: