题意:
给定一个六边形坐标系统,从(0,0)出发,走环,求N≤1018步的坐标
分析:
显然,路径是一个环套一个环,下一个环插入了6个新的六边形,f(n)=f(n−1)+6,f(0)=1
首先先二分确定之前有多少环,然后求余数r
每个环的走法,都是6个方向,每个方向的步数是x(第x个环)
假设从(2x,0)出发,作为虚拟的第0步,我们可以通过变换规律求得r步的坐标
当然如果r=0,坐标就是(2×(x−1),0)
代码:
//
// Created by TaoSama on 2016-01-09
// Copyright (c) 2015 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
typedef long long LL;
LL n;
int d[][2] = {{ -1, 2}, { -2, 0}, { -1, -2}, {1, -2}, {2, 0}, {1, 2}};
int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
// freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
while(scanf("%I64d", &n) == 1) {
LL l = 1, r = 1e9;
while(l <= r) {
LL m = l + r >> 1;
if(3 * m * (m + 1) <= n) l = m + 1;
else r = m - 1;
}
n -= 3 * l * (l - 1);
if(!n) {printf("%I64d 0\n", l - 1 << 1, 0); continue;}
LL x = l << 1, y = 0;
for(int i = 0; i < 6; ++i) {
LL k = min(n, l);
x += k * d[i][0];
y += k * d[i][1];
n -= k;
}
printf("%I64d %I64d\n", x, y);
}
return 0;
}