公式
G - AtCoder Wallpaper 解説
by
G - AtCoder Wallpaper 解説
by
Cyanmond

壁紙の模様はこの \(4 \times 2\) の長方形内の模様が無限に続いています。よって、 \(4 \times 2\) の長方形内にある \(8\) 個の \(1 \times 1\) の正方形それぞれについて、それが与えられた長方形内にいくつ存在するかを求めることで、この問題を解くことができます。
長方形内に各位置の正方形がいくつ存在するかを求めるとき、境界での \(1\) ずれなどが複雑かもしれません。一例として、下の実装では次のようにしています。
- \(x, y\) 方向それぞれについていくつ正方形が並んでいるかを独立に求め、最後に掛け合わせることにする。
- \(x\) 方向にいくつ並んでいるかを求めるときは、十分大きな \(4\) の倍数の定数 \(P\) (例えば \(1.1 \times 10^9\) など) をとって、 \((x = -P と x = C の間にある個数) - (x = -P と x = A の間にある個数)\) の形で求める。
- \(P\) は負の値の割り算が \(0\) 方向に丸められることの回避のために用いています。
- \(y\) 方向についても同様の形で求める。
また、このような問題のデバッグでは自分で色々なケースを作ってみるのも有用です。今回の問題では、原因が境界の \(1\) ずれであれば、 \(0 \leq A, B, C, D \leq 8\) ほどの範囲でいろいろなケースを試してみるとバグが見つかるはずです。
実装例 (C++) :
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
constexpr int mass[2][4] = {
{2, 1, 0, 1},
{1, 2, 1, 0}
};
// mass[i][j] : 長方形 [[j, j + 1], [i, i + 1]] の面積 x 2
constexpr i64 inf = 4000000000ll;
int main() {
// 入力
i64 a, b, c, d;
cin >> a >> b >> c >> d;
// 計算
i64 ans = 0;
for (int fy = 0; fy < 2; ++fy) {
for (int fx = 0; fx < 4; ++fx) {
const i64 x1 = (a - fx + 3 + inf) / 4, x2 = (c - fx + 3 + inf) / 4;
const i64 count_x = x2 - x1; // x 方向の個数
const i64 y1 = (b - fy + 1 + inf) / 2, y2 = (d - fy + 1 + inf) / 2;
const i64 count_y = y2 - y1; // y 方向の個数
ans += count_x * count_y * mass[fy][fx];
}
}
// 出力
cout << ans << endl;
}
投稿日時:
最終更新:
