第七題 標題:螺旋折線(18年第七題)
如圖 所示的螺旋折線經過平面上所有整點恰好一次。
對於整點(X, Y),我們定義它到原點的距離dis(X, Y)是從原點到(X, Y)的螺旋折線段的長度。
例如dis(0, 1)=3, dis(-2, -1)=9
給出整點座標(X, Y),你能計算出dis(X, Y)嗎?
定義數值:
設當前所在螺旋層數爲 C 層。
第一步:分析出特殊的有規律的點。
右上頂點: 值爲 **(C * 2)^2 ** 設爲 M
左下頂點: 值爲 **(c * 2 - 1) ^2 ** 設爲 N
由特殊點製造有用點,方便解題。
將象限交界點用 M, N, C 表示,然後對螺旋經行分割。(按象限經行分割)。
下一步就是推算點的計算公式。由於對象限經行分割,那麼每個象限都可以取不同的參考點。
第三象限爲兩層螺旋交接處,要經行分段處理。
以下便是測試代碼,對於題目中的100%數據範圍最大10億也可以通過。
如果不清楚,可以複製代碼運行查看結果,然後再模擬畫一下螺旋圖,想必便知道解法了。
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#define Max(a, b) ((a) > (b) ? (a) : (b))
typedef long long ll;
// 劃分象限
int dir(ll x, ll y){
if(x >= 0){
if(y >= 0){
return 1;
} else {
return 4;
}
}else{
if(y >= 0){
return 2;
}else{
return 3;
}
}
}
ll get(ll x, ll y){
// 這裏用位運算代替許多乘法可以提高速度。
// 10 >> 1 = 5 (>>1相當於除2)
// 10 << 1 = 20 (<<1相當於乘2)
printf("輸入座標: (%lld, %lld)\n", x, y);
ll ceng = Max(abs(x), abs(y));
printf("座標所在螺旋層數: %lld\n", ceng);
// (2*x)^2
ll n = ((ceng << 1) - 1) * ((ceng << 1) - 1);
ll m = ((ceng << 1) * (ceng << 1));
printf("所在螺旋層數左下角頂點: %lld\n", n);
printf("所在螺旋層數右上角頂點: %lld\n", m);
ll re = 0;
switch(dir(x, y)){// 處理各個象限
case 1:
printf("1象限: 1象限與2象限交點: %lld\n", m - ceng);
re = (m - ceng) + ((ceng) - (y - x));
break;
case 2:
printf("2象限: 2象限與3象限交點: %lld\n", n + ceng -1);
re = (n + ceng - 1) + (ceng + (x + y));
break;
case 3:
if(y <= x){// 分段處理
printf("3象限: 3象限與4象限交點: %lld\n", m + (ceng << 1) + ceng);
re = (m + (ceng << 1) + ceng) + (- x);
}else{
printf("3象限: 3象限與4象限交點: %lld\n", n + ceng - 1);
re = (n + ceng - 1) + (y);
}
break;
case 4:
printf("4象限: 1象限與4象限交點: %lld\n", m + ceng);
re = (m + ceng) + (ceng - x - y);
break;
}
}
int main(){
ll x = 1000000000;
ll y = -1000000000;
ll result = get(x, y);
printf("結果: %lld\n", result);
return 0;
}