巨集的陷阱

1.0s 256M

多數的人在學 C++ 的 #define 的用法時(此語法中文翻為「巨集」),會錯把 #define F(X) 當作函式來用。

拿以下問題為例:

給你二維平面上的兩個點 \(A\) 和 \(B\),\(A\) 的座標為 \((A_x,A_y)\),\(B\) 的座標為 \((B_x, B_y)\),請計算點 \(A\) 和點 \(B\) 兩個點間直線距離的平方。

我們知道,兩個點的距離公式為 \(\sqrt{(A_x - B_x)^2 + (A_y - B_y)^2}\),所以平方後的結果為 \((A_x - B_x)^2 + (A_y - B_y)^2\),此公式出現了兩次平方的計算。有些人會選擇把平方用「巨集」來表示,寫成程式碼如下:

#include<iostream>
using namespace std;
#define SQR(X) X * X
int main() {
    int A_x, A_y, B_x, B_y;
    cin >> A_x >> A_y >> B_x >> B_y;
    cout << SQR(A_x - B_x) + SQR(A_y - B_y) << endl;
    return 0;
}

但這樣子答案卻是錯的,例如,當點 \(A\) 為 \((2, 1)\),點 \(B\) 為 \((-2, -2)\) 時,此份程式碼會輸出 \(13\),但答案應該是 \((2-(-2))^2 + (1 - (-2))^2 = 25\)。

這是因為編譯器會把 \(SQR(A\_x - B\_x) + SQR(A\_y - B\_y)\) 取代為 \(A\_x - B\_x * A\_x - B\_x + A\_y - B\_y * A\_y - B\_y\)。正確的巨集寫法應為如下

#define SQR(X) ((X) * (X))

本題要大家寫一份程式碼來實驗巨集的錯誤寫法和正確寫法,輸入會給你點 \(A\) 和點 \(B\) 的座標,請依序輸出以上所列的錯誤程式碼的將會輸出的答案以及正確的答案。

輸入格式

輸入只有一行,包含四個整數,依序為 \(A_x, A_y, B_x, B_y\)。輸入滿足 \(-10,000 \le A_x, A_y, B_x, B_y \le 10,000\)。

輸出格式

輸出一行包含兩個整數,第一個整數是題敘裡錯誤的程式碼輸出的答案,第二個數字是正確的答案。

評分說明

此題佔 \(20\) 分。

範例輸入 1

2 1 -2 -2

範例輸出 1

13 25

題目頁說明

快速鍵

主要功能

  • 範例測試 — 執行題目附帶的範例測資並自動比對預期輸出。
  • 自訂測試 — 自己貼 stdin 執行程式。可勾選「與預期輸出比對 (diff)」做行對行比對。
  • 模板 — 貼上你在個人資料設定的預設程式碼模板。
  • 協作 — 與其他同學共筆編輯這題的程式碼。
  • 自動草稿 — 編輯器內容每 1.5 秒自動存到瀏覽器(per 帳號 / 題目 / 語言)。
  • 提交 — 把程式碼交給 judge 評測,回傳 AC / WA / TLE 等結果。

限制

  • 程式碼最多 65,536 字元
  • 自訂測試 stdin 與預期輸出各最多 1 MB (約 100 萬字元)
  • 自訂測試與範例測試共用一個沙箱,每人約 3 秒 1 次 (範例測試 1 秒 1 次)
  • 自訂測試與範例測試都有 15 秒 牆鐘上限(正式評測仍依題目原本時限)
  • 互動題不提供自訂測試(無法模擬與 judge 互動)。
  • 提交評測本身沒有 rate limit,但同題短時間內多次提交會被視為刷分。