题意

讨论区里的翻译挺不错的,可以去看看。

大致意思是给定了一种坐标系和一种编号方法,将每个编号转化为对应的坐标。

分析

大佬们的奇怪思路我不理解,不过这个数据范围决定了它就是一道橙题。

保证每个编号小于 1 0 5 10^5 105,我预处理一下不就完事了吗。

具体如何模拟呢?

最开始的 8 8 8 个不太好处理规律,直接填写答案,从第九个开始分为 6 6 6 个方向。

  • 左上方,横坐标减一。
  • 上方,纵坐标减一。
  • 右上方,横坐标加一,纵坐标减一。
  • 右下方,横坐标加一。
  • 下方,纵坐标加一。
  • 左下方,横坐标减一,纵坐标加一。

如果横坐标或纵坐标为零或者横纵坐标相加为零,就变换方向。

如果纵坐标为零,横坐标大于零,就说明这一圈结束了,需要停止变换方向一次,过了这个编号再转方向。

代码

#include<bits/stdc++.h>
using namespace std;
int a1,a2,b1,b2,a[1000005],b[1000005],t=1,da[10]={
   0,-1,-1,0,1,1},db[10]={
   1,1,0,-1,-1,0},n,f;
int main()
{
   
  a[1]=a[2]=a[5]=b[1]=b[4]=b[7]=0;
  a[3]=a[4]=b[5]=b[6]=-1;
  a[6]=a[7]=b[2]=b[3]=1;
  a[8]=b[8]=1;
  a1=1;
  b1=1;
  f=0;
  for(int i=9;i<1000001;i++)
  {
   
    a2=a1+da[t];
    b2=b1+db[t];
    a1=a2;
    a[i]=a2;
    b1=b2;
    b[i]=b2;
    if(f)
    {
   
      f=0;
      t++;
    }
    if(a1>0&&b1==0)
    {
   
      f=1;
      continue;
    }
    if(a1==0||b1==0||a1+b1==0)t=(t+1)%6;
  }
  while(~scanf("%d",&n))cout<<a[n]<<" "<<b[n]<<endl;//注意多测。
  return 0;
}