不是VIP会员,不能显示答案

题目解答

题目:
(大整数开方)输入一个正整数n(1<=n<10^100),试用二分法计算它的平方根的整数部分。
const
	SIZE=200; 
type
	hugeint = record
		len : integer;
		num : array[1..SIZE] of integer;
	end;	//len表示大整数的位数;num[1]表示个位、num[2]表示十位,以此类推(这个注释不是我带鱼灰写的,是原试题带有的)
var
	s : string;
	i : integer;
	target, left, middle, right : hugeint; 
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
		for j:=1 to b.len do
    ans.num[i+j-1] :=ans.num[i + j - 1] + a.num[i] * b.num[j];
	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 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 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
		target.num[i] := ord(s[target.len - i +1]) - ord(‘0’) ;
	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.
考点: 0
分析:
解答: 本届的完善程序和阅读程序的程序都写得很规范,有良好可读性。浏览一下这题,二分法+高精度,然后看各个函数过程的功能。
凭借良好的英文功底,我们知道add就是加,看这个function add里面,的确是a+b,然后我们就可以很快得出③,注意之前有进位,它还要加上它自己。
既然这一模块唯一的空已经很快填好了,我们就不看这块了,知道这是个a+b的函数就行了。接下来看到average,average就是平均,看主过程,middle:=average(left,right);,这绝对是求a和b的平均值错不了了!里面有个④,我们可以轻松看出④所在的循环是ans已经等于a+b了,现在正在除以2。模拟我们笔算用的竖式除法,我们知道④这个地方是进位,就用ans.num[i] mod 2就行了。
然后我们看到plustwo,plustwo的意思就是“加二”,这里面只有一个空,是⑤。不用看上面,只看⑤所在的if语句,我们就知道这里应该是对ans.len的修正,应该填inc(ans.len)。
再看到over,在主程序里我们知道这是个二分用的东西。看到over中的if a.len>b.len这段,得知如果a比b长,也就是a比b大,那over就为真。看来这个over就是个比大小的函数,a>b为真,a
评论:
老师: 0