螺旋折線(18年第七題)

第七題 標題:螺旋折線(18年第七題)

如圖 所示的螺旋折線經過平面上所有整點恰好一次。
對於整點(X, Y),我們定義它到原點的距離dis(X, Y)是從原點到(X, Y)的螺旋折線段的長度。
例如dis(0, 1)=3, dis(-2, -1)=9
給出整點座標(X, Y),你能計算出dis(X, Y)嗎?
p1.png
在這裏插入圖片描述

定義數值:
設當前所在螺旋層數爲 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;
} 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章