您的位置:首页 > 其它

noip2011初赛-大整数开方

2015-08-23 17:27 330 查看
noip2011C_4_2(大整数开方)输入一个正整数n(1<=n<=10^100),试用二分法计算它的平方根的整数部分。

const
SIZE=200;

type
hugeint=record
len:integer;
num:array[1..SIZE] of integer;
end;

var
s:string;
i:integer;
target,left,middle,right:hugeint;

function add(a,b:hugeint):hugeint;
var
i:integer;
ans:hugeint;
begin
	fillchar(ans.num,sizeof(ans.num),0);
	if a.len>b.len then ans.len:=a.len
	else ans.len:=b.len;
	for i:=1 to ans.len do
	begin
		ans.num[i]:=ans.num[i]+a.num[i]+b.num[i];
		ans.num[i+1]:=ans.num[i+1]+ans.num[i] div 10;
		ans.num[i]:=ans.num[i] mod 10;
	end;
	if ans.num[ans.len+1]>0 then inc(ans.len);
	add:=ans;
end;

function times(a,b:hugeint):hugeint;
var
i,j:integer;
ans:hugeint;
begin
	fillchar(ans,sizeof(ans),0);
	for i:=1 to a.len do
	begin
		for j:=1 to b.len do
		begin
			ans.num[i+j-1]:=ans.num[i+j-1]+a.num[i]*b.num[j];
		end;
	end;
	for i:=1 to a.len+b.len do
	begin
		ans.num[i+1]:=ans.num[i+1]+ans.num[i] div 10;
		ans.num[i]:=ans.num[i] mod 10;
		if ans.num[a.len+b.len]>0 then ans.len:=a.len+b.len
		else ans.len:=a.len+b.len-1;
	end;
	times:=ans;
end;

function average(a,b:hugeint):hugeint;
var
i:integer;
ans:hugeint;
begin
	ans:=add(a,b);
	for i:=ans.len downto 2 do
	begin
		ans.num[i-1]:=ans.num[i-1]+(ans.num[i] mod 2)*10;
		ans.num[i]:=ans.num[i] div 2;
	end;
	ans.num[1]:=ans.num[1] div 2;
	if ans.num[ans.len]=0 then dec(ans.len);
	average:=ans;
end;

function plustwo(a:hugeint):hugeint;
var
i:integer;
ans:hugeint;
begin
	ans:=a;
	ans.num[1]:=ans.num[1]+2;
	i:=1;
	while(i<=ans.len) and (ans.num[i]>=10) do
	begin
		ans.num[i+1]:=ans.num[i+1]+ans.num[i] div 10;
		ans.num[i]:=ans.num[i] mod 10;
		inc(i);
	end;
	if ans.num[ans.len+1]>0 then inc(ans.len);
	plustwo:=ans;
end;

function over(a,b:hugeint):boolean;
var
i:integer;
begin
	if (a.len<b.len) then
	begin
		over:=false;
		exit;
	end;
	if (a.len>b.len) then
	begin
		over:=true;
		exit;
	end;
	for i:=a.len downto 1 do
	begin
		if a.num[i]<b.num[i] then
		begin
			over:=false;
			exit;
		end;
		if a.num[i]>b.num[i] then
		begin
			over:=true;
			exit;
		end;
	end;
	over:=false;
end;

begin
	readln(s);
	fillchar(target.num,sizeof(target.num),0);
	target.len:=length(s);
	for i:=1 to target.len do
	begin
		target.num[i]:=ord(s[target.len-i+1])-ord('0');
	end;
	fillchar(left.num,sizeof(left.num),0);
	left.len:=1;
	left.num[1]:=1;
	right:=target;
	repeat
		middle:=average(left,right);
		if over(times(middle,middle),target) then right:=middle
		else left:=middle;
	until over(plustwo(left),right);
	for i:=left.len downto 1 do write(left.num[i]);
	writeln;
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: