問題
$N$ 頂点の単純多角形(頂点は整数座標、自己交差なし)が与えられる。以下を求めよ:
- 面積: 多角形の面積(整数または半整数)
- 内部格子点数: 多角形の厳密な内部にある格子点の数(辺上は含まない)
- 辺上格子点数: 多角形の辺上にある格子点の数(頂点を含む)
制約
| パラメータ | 範囲 | 備考 |
|---|---|---|
| $N$ | $3 \le N \le 10^5$ | 頂点数 |
| 座標 | 整数、$|x|, |y| \le 10^9$ | |
| 格子点数 | $\le 10^{18}$ |
入出力例
入力例1(正方形)
4
0 0
5 0
5 5
0 5
出力例1
面積: 25
辺上格子点: 20
内部格子点: 16
入力例2(直角三角形)
3
0 0
4 0
0 3
出力例2
面積: 6
辺上格子点: 8
内部格子点: 3
概念図: Pick の定理
ヒント
ヒント1(方向性)
- 面積: Shoelace 公式で $O(N)$、整数演算で誤差なし
- 辺上格子点数 $B$: 各辺 $\gcd(|\Delta x|, |\Delta y|)$ の総和
- 内部格子点数 $I$: Pick の定理 $I = A - B/2 + 1 = (2A - B + 2)/2$
ヒント2(アプローチ)
- Shoelace: $2A = |\sum_{i=0}^{N-1} (x_i y_{i+1} - x_{i+1} y_i)|$
- 辺上: $B = \sum_{i=0}^{N-1} \gcd(|x_{i+1}-x_i|, |y_{i+1}-y_i|)$
- Pick: $I = (2A - B + 2) // 2$
ヒント3(ほぼ答え)
from math import gcd
area2 = 0
for i in range(N):
x1, y1 = pts[i]; x2, y2 = pts[(i+1)%N]
area2 += x1*y2 - x2*y1
area2 = abs(area2)
B = sum(gcd(abs(pts[(i+1)%N][0]-pts[i][0]),
abs(pts[(i+1)%N][1]-pts[i][1])) for i in range(N))
I = (area2 - B + 2) // 2
模範解答
import sys
from math import gcd
input = sys.stdin.readline
def solve():
N = int(input())
pts = [tuple(map(int, input().split())) for _ in range(N)]
# Shoelace 公式で 2*面積 を計算(整数)
area2 = 0
for i in range(N):
x1, y1 = pts[i]
x2, y2 = pts[(i+1) % N]
area2 += x1 * y2 - x2 * y1
area2 = abs(area2)
# 辺上格子点数 B
B = 0
for i in range(N):
x1, y1 = pts[i]
x2, y2 = pts[(i+1) % N]
B += gcd(abs(x2-x1), abs(y2-y1))
# Pick の定理: I = (2A - B + 2) / 2
I = (area2 - B + 2) // 2
if area2 % 2 == 0:
area_str = str(area2 // 2)
else:
area_str = f"{area2 // 2}.5"
print(f"面積: {area_str}")
print(f"辺上格子点: {B}")
print(f"内部格子点: {I}")
solve()
Step-by-Step 解説
Step 1: Shoelace(ガウスの面積)公式
$$2A = \left|\sum_{i=0}^{N-1} (x_i y_{i+1} - x_{i+1} y_i)\right|$$
各辺ベクトルの外積の総和の絶対値。整数座標なら誤差ゼロ。計算量 $O(N)$。
Step 2: 辺上の格子点数
線分 $(x_1, y_1) \to (x_2, y_2)$ 上の格子点数(両端含む)= $\gcd(|\Delta x|, |\Delta y|) + 1$。多角形全体では各辺の $\gcd$ を足す(隣接頂点を一度だけカウント)。
証明: $g = \gcd(dx, dy)$ とすると、方向ベクトル $(dx/g, dy/g)$ が最小ステップ。途中の格子点は $g-1$ 個(両端除く)。
Step 3: Pick の定理
$$A = I + \frac{B}{2} - 1 \implies I = \frac{2A - B + 2}{2}$$
$2A$ と $B$ はともに整数なので、$I$ が整数になることが保証される。
よくあるミス
| ミス | 原因 | 正しい書き方 |
|---|---|---|
| area2 の符号が負 | 時計回りの入力 | abs(area2) で絶対値 |
| B のカウントで辺の両端を二重カウント | gcd+1 を足す | gcd(dx, dy) のみ足す |
| $I$ の整数性を確認しない | 非格子点多角形では成立しない | 整数座標多角形の前提を確認 |
gcd(0, 0) のエラー | 同一頂点の辺 | 多角形では辺長 0 は起きない |
次のステップ
- 発展: 3D 多面体の体積と格子点数(Ehrhart 多項式)
- 発展: 格子点多角形のラティス・バンドル
- 発展: 非格子点多角形の面積最小化問題
自己評価
理解度:
自分の回答:
気づき・メモ: