題意#
題目給定一個以螺旋狀向外無限延伸的數字方陣。
現在給定某個格子的行座標 y 和列座標 x,我們要推算出這個格子裡面填的數字是多少。
因為座標可能高達 \( 10^9 \),直接把陣列建出來絕對會把記憶體撐爆(MLE),所以只能靠數學規律去解。
思路#
這題破局的關鍵就在陣列的「對角線」上。
如果你把對角線(也就是 x == y 的那些格子)的數字挑出來看,像是 1, 3, 7, 13…,會發現它們都有一個好用的通式:第 \( y \) 層對角線的數字剛好是 \( 1 + y \times (y - 1) \)。例如當 \( y=3 \) 時,對角線上的值就是 \( 1 + 3 \times 2 = 7 \)。
既然我們能瞬間算出「那層的對角線」數值是多少,剩下的任務就只剩找「偏移量」而已。
為了讓程式碼更簡潔,我們可以強制把較大的那個座標當成基準 y。如果一開始 x > y,就把兩者交換,並用變數 k 標明我們有「轉向」過。接著只要判斷這層是奇數層還是偶數層(因為它們螺旋成長的方向是反的),算出與對角線的距離差距 y - x,再乘上方向修正值 k,就能直接算出目標格子的答案。
程式碼#
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define fi first
#define se second
#define INF LONG_LONG_MAX/1000
#define WA() cin.tie(0)->sync_with_stdio(0)
#define all(x) (x).begin(), (x).end()
#define int long long
#define PII pair<int, int>
signed main() { WA();
int t;
// 讀入測資數量並執行 t 次迴圈
for (cin >> t; t--;) {
// y: 列,x: 行,k: 方向修正值 (預設為 1)
int y, x, k = 1; cin >> y >> x;
// 如果行座標大於列座標,交換兩者以強制 y 為基準,並將方向修正值改為 -1
if (x > y) k = -1, swap(x, y);
// 判斷當前基準 y 是奇數層還是偶數層 (奇偶層螺旋方向相反)
if (y&1) cout << 1+y*(y-1) - (y-x)*k << '\n'; // 奇數層
else cout << 1+y*(y-1) + (y-x)*k << '\n'; // 偶數層
}
}
