| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
为神马这题有1400+个ac但pascal的却只有16个?答案内详1.这道题目数据出的比较尴尬。如果用O(n^3)朴素算法水的话,C++是可以水过去的,但pascal不管怎么
常数优化都水不过去。
2.那好吧,我用O(n^2lgn)的算法吧。但这时蛋疼的事情出现了:由于需要获得两个圆相交的弧的角度,
需要用arctan和arctan2.但这两个东西在math单元里才有,而且math单元被POJ封掉了(很奇
怪,C++/G++并没有封掉math.h,但pascal封掉了unit math)。于是pascal悲剧了。
3.没事!我自己泰勒展开+各种特判手动写arctan和arctan2!写完了,精度不够。怎么调eps、迭代次数
都没用。再次悲剧。
4.好吧……我去翻free pascal的source code,把math单元源码翻一遍,总能找到这东西的实现的!翻
完,发现没有……(这一点我不能肯定,毕竟没有函数原型却能编译出来一个函数是不现实的事。但我Ctrl+F
了numlib文件夹中的每一个文件,都没有找到arctan和arctan2的函数原型,更没有函数实现了,不知原
因)。
5.最后……把math库里arcsin的实现复制过来当arctan用,手动写arctan2,终于ac了……而且因为中途
多了一步sqrt,只要多写一个浮点除法精度就又不够了。
帮助pascal党后人,留下pascal版atan2的实现,需要的可以去用
前两个函数来自math单元源码,最后一个是我手写的。
arfloat0 = array[0..20000] of extended;
function spepol(x: extended; var a: extended; n: longint): extended;
var pa : ^arfloat0;
i : longint;
polx : extended;
begin
pa:=@a;
polx:=0;
for i:=n downto 0 do
polx:=polx*x+pa^[i];
spepol:=polx
end;
function spears(x: extended): extended;
const
pi2 = 1.570796326794897;
a : array[0..17] of extended =
( 1.047197551196598e+0, 5.375149359132719e-2, 7.798902238957732e-3,
1.519668539582420e-3, 3.408637238430600e-4, 8.302317819598986e-5,
2.134554822576075e-5, 5.701781046148566e-6, 1.566985123962741e-6,
4.402076871418002e-7, 1.257811162594110e-7, 3.646577948300129e-8,
1.081021746966715e-8, 3.212744286269388e-9, 8.515014302985799e-10,
2.513296398553196e-10, 1.342121568282535e-10, 4.210346761190271e-11);
var y, u, t, s : extended;
uprang : boolean;
begin
u:=sqr(x); uprang:= u > 0.5;
if uprang
then
u:=1-u;
t:=4*u-1; y:=spepol(t, a[0], sizeof(a) div sizeof(extended) - 1);
if uprang
then
begin
s:=pi2-sqrt(u)*y;
if x < 0
then
s:=-s;
spears:=s
end
else
spears:=x*y
end;
function atan2(const x,y:extended):extended;
var res:extended;
begin if x=0 then if y<0 then exit(pi) else exit(0);
if y=0 then if x<0 then exit(-pi/2) else exit(pi/2);
res:=spears(y/sqrt(sqr(x)+sqr(y)));
if (y>0)and(x>0) then exit(pi/2-res);
if (y>0)and(x<0) then exit(-pi/2+res);
if (y<0)and(x>0) then exit(pi/2-res);
if (y<0)and(x<0) then exit(-pi/2+res);
end;
Followed by:
Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator