分形之城
(fra.pas/c/cpp)
题目描述
城市的规划在城市建设中是个大问题。不幸的是,很多城市在开始建设的时候并没有很好的
规划,城市规模扩大之后规划不合理的问题就开始显现。而这座名为Fractal 的城市设想了
这样的一个规划方案,如下图所示:
当城区规模扩大之后,Fractal 的解决方案是把和原来城区结构一样的区域按照图中的方式
建设在城市周围,提升城市的等级。对于任意等级的城市,我们把正方形街区从左上角开
始按照道路标号。虽然这个方案很烂,Fractal 规划部门的人员还是想知道,如果城市发展
到了等级N,编号为A 和B 的两个街区的直线距离是多少。街区的距离指的是街区的中心
点之间的距离,每个街区都是边长为10 米的正方形。
输入格式
输入文件包含多组测试数据,第一行有一个整数T 表示测试数据的数目。
每组测试数据包含一行三个整数 N, A, B,表示城市等级以及两个街区的编号。
输出格式
对于每组测试数据,在单独的一行内输出答案,四舍五入到整数。
样例输入
3
1 1 2
2 16 1
3 4 33
样例输出
10
30
50
数据范围与约定
对于30% 的数据,N≤5,T≤10。
对于 100% 的数据,N≤31,1≤A,B≤22N。T≤1000。
对于这道题,显然,范围太大,我们要根据图来一步步缩小范围,算是分治/递归?吧
但是,图翻来覆去的(*-*)+_+
咋办?
大神说有公式,有规律,可是,身为蒟蒻的我不会。。。。。。
Orz
难道放弃?不!
我们可以发现,最多也只有4种规则,而每一种规则将图化为4部分,每一个部分又对应另一种规则(确定的),那么,最多一共有4*4=16种规则方式
然后,。。。。。。。打表(别说我无耻)
program ex03; const ne:array[0..3,0..3] of longint=((1,0,2,0), //对应关系 (0,3,1,1), (2,2,0,3), (3,1,3,2)); ch:array[0..3,0..3] of longint=((0,1,3,2), //放置规则 (0,2,3,1), (3,1,0,2), (3,2,0,1)); var n,a,b:qword; t,i:longint; function qm(a,b:qword):qword; var t,sum:qword; i:longint; begin sum:=1; for i:=1 to b do sum:=sum*a; exit(sum); end; procedure init; begin readln(n,a,b); a:=a-1; b:=b-1; end; procedure find(a,p:qword; q:double; k:qword; var x,y:double); //一直缩小范围 var i:qword; begin i:=a div p; //放置规则 if ch[k][i]=0 then begin x:=x-q; y:=y-q; end else if ch[k][i]=1 then begin x:=x-q; y:=y+q; end else if ch[k][i]=2 then begin x:=x+q; y:=y-q; end else if ch[k][i]=3 then begin x:=x+q; y:=y+q; end; k:=ne[k][ch[k][i]]; //下一个要选哪个策略 if p=1 then exit; a:=a mod p; find(a,p div 4,q/2,k,x,y); end; procedure doit; var p,q:qword; xa,ya,xb,yb,o:double; s,x,y:double; begin p:=qm(4,n-1); //不要用快速幂;我是炸了无数次后才改的循环,其实时间差不多 q:=qm(2,n-1); o:=q; xa:=q; ya:=q; xb:=q; yb:=q; find(a,p,o/2,0,xa,ya); find(b,p,o/2,0,xb,yb); s:=sqrt(sqr(ya-yb)+sqr(xa-xb)); writeln(trunc(s*10+0.5)); //注意,一定要最后*10,不然会炸; end; begin assign(input,'fra.in'); reset(input); assign(output,'fra.out'); rewrite(output); readln(t); for i:=1 to t do begin init; doit; end; close(input); close(output); end.