poj 8463
典型分治算法。转换坐标和转换方向是等价的。long long用起来要注意,除法可能有点奇怪。算cnt的时候刚开始用了除法,总是不对,改成while循环就好了。四舍五入要用printf。
#include <iostream>
#include <string.h>
#include <cstring>
#include <queue>
#include <cmath>
using namespace std;
#define ll long long
int map[4][4][2]={{0,0,0,1,1,1,1,0},{0,0,1,0,1,1,0,1},
{1,1,1,0,0,0,0,1},{1,1,0,1,0,0,1,0}};
int n;
ll p1,p2;
void work(int n,ll p,ll &x,ll &y,int m)//m=0,1,2,3
{
//cout<<n<<' '<<p<<' '<<x<<' '<<y<<' '<<m<<endl;
if(n==1)
{
x+=map[m][(int)p-1][0];
y+=map[m][(int)p-1][1];
return;
}
int cnt=0;int t=2*n-2;
while((p-(1ll<<t))>0){cnt++;p-=(1ll<<t);}
//cout<<cnt<<endl;
x+=(map[m][cnt][0]*(1ll<<(n-1)));
y+=(map[m][cnt][1]*(1ll<<(n-1)));
if(m==0)
{
if(cnt==0)m=1;
if(cnt==3)m=3;
}
else if(m==1)
{
if(cnt==0)m=0;
if(cnt==3)m=2;
}
else if(m==2)
{
if(cnt==0)m=3;
if(cnt==3)m=1;
}
else if(m==3)
{
if(cnt==0)m=2;
if(cnt==3)m=0;
}
work(n-1,p,x,y,m);
}
int main()
{
int t;cin>>t;
while(t--)
{
cin>>n>>p1>>p2;
ll X1=0;ll X2=0;
ll Y1=0;ll Y2=0;
work(n,p1,X1,Y1,0);
work(n,p2,X2,Y2,0);
//cout<<X1<<' '<<X2<<' '<<Y1<<' '<<Y2<<endl;
printf("%.0lf\n",sqrt((X1-X2)*(X1-X2)*100.0+(Y1-Y2)*(Y1-Y2)*100.0));
}
return 0;
}