题意
- 在一个二维直角坐标系下,铺满了正六边形,然后从中间的正六边形沿着图上给出的方向走n步,问最后所在的正六边形的坐标位置
思路
- 首先,可以注意到x,y坐标的尺度不同,x方向上是边长的根3倍为2,y是边长的1倍为2,不过其实这点,也不太重要啦。。。只不过是方便算下坐标而已。。
- 然后,很好想到,每一圈的六边形数是1,6,12,….,所以用等差数列求和可以得到总数,那么二分答案,就可以得到n步之后,在第m圈上了
- 然后呢,在第m个六边形六个边上的情况上是不同的,所以我们判断一下在哪条边上,分开处理即可(这里也可以用一些对称的性质,简化代码,不过不用也挺好写的。。)
- 注意,n是步数,不是在第几个六边形上,所以可以先n++
实现
#include <bits/stdc++.h>
using namespace std
typedef long long ll
typedef pair<ll,ll> pll
#define fi first
#define se second
#define pb push_back
#define mp make_pair
const int inf = 0x3f3f3f3f
pll getNum(ll n,ll m){
ll tmp = n - 3 * m * (m+1) - 1
return mp(tmp / (m+1), tmp % (m+1))
}
pll getPoint(ll m,pll num){
pll chu
pll ret
switch (num.fi){
case 0:
chu.fi = 2 * (m+1) - 1
chu.se = 2
ret.fi = chu.fi - num.se
ret.se = chu.se + 2 * num.se
break
case 1:
chu.fi = (m+1) - 2
chu.se = 2 * (m+1)
ret.fi = chu.fi - 2 * num.se
ret.se = chu.se
break
case 2:
chu.fi = -(m+1) - 1
chu.se = 2 * (m+1) - 2
ret.fi = chu.fi - num.se
ret.se = chu.se - 2 * num.se
break
case 3:
chu.fi = -2 * (m+1) + 1
chu.se = -2
ret.fi = chu.fi + num.se
ret.se = chu.se - 2 * num.se
break
case 4:
chu.fi = -(m+1) + 2
chu.se = - 2 * (m+1)
ret.fi = chu.fi + 2 * num.se
ret.se = chu.se
break
case 5:
chu.fi = (m+1) + 1
chu.se = - 2 * (m+1) + 2
ret.fi = chu.fi + num.se
ret.se = chu.se + 2 * num.se
break
}
return ret
}
int main(){
ll m,n
cin>>n
if (n == 0){
puts("0 0\n")
return 0
}
ll low = 0, high = inf
while (high >= low){
ll mid = (high + low) / 2
if (3 * mid * (mid+1) + 1 <= (n+1)){
m = mid
low = mid + 1
}
else{
high = mid - 1
}
}
if (3 * m * (m+1) + 1 == (n+1)){
m --
}
pll ans = getPoint(m,getNum(n,m))
cout << ans.fi <<" " <<ans.se << "\n"
return 0
}