Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

为神马这题有1400+个ac但pascal的却只有16个?答案内详

Posted by xuhaoran510 at 2011-06-29 22:36:26 on Problem 1981 and last updated at 2011-06-29 22:39:50
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:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator