观察图像,如果城市从等级i变为等级i+1,则等级i的左上、右上、右下、左下四个区域从等级i-1变为等级i,同时,观察这四个区域,我们可以知道右上和右下两个区域和一阶的方向是一致的,左上的方向是一阶的方向顺时针转90°,左下的方向是一阶的方向逆时针转90°。
现在考虑如何解决本题。我们要求两个街区的距离,我们可以求出这两个街区的坐标,然后用距离公式求得。所以现在的问题转变为由街区编号k求坐标。对于第i-1阶的城市,其边长len为2i-1,街区个数为cnt=len*len。所以对于第i阶,k%cnt就是该街区所在子城市的编号,k/cnt就是该子城市的位置。所以我们递归求解子城市,再根据子城市的位置不同对坐标做变换。
具体如下:
PII f(ll n,ll x){
if(n==0)return {0,0};
ll len=1<<n-1,cnt=len*len;
PII tmp=f(n-1,x%cnt);
ll u=x/cnt;
int xx=tmp.first,yy=tmp.second;
if(u==0)return {yy,xx};
if(u==1)return {xx,yy+len};
if(u==2)return {xx+len,yy+len};
return {2*len-1-yy,len-1-xx};
}
完整代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
typedef pair<ll,ll> PII;
PII f(ll n,ll x){
if(n==0)return {0,0};
ll len=1<<n-1,cnt=len*len;
PII tmp=f(n-1,x%cnt);
ll u=x/cnt;
int xx=tmp.first,yy=tmp.second;
if(u==0)return {yy,xx};
if(u==1)return {xx,yy+len};
if(u==2)return {xx+len,yy+len};
return {2*len-1-yy,len-1-xx};
}
void solve(){
ll n,a,b;
cin>>n>>a>>b;
a--,b--;
PII p1=f(n,a),p2=f(n,b);
ll x1=p1.first,y1=p1.second,x2=p2.first,y2=p2.second;
printf("%.lf\n",(10*sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))));
}
int main(){
int T;
cin>>T;
while(T--)solve();
return 0;
}