新浪博客

棋盘放麦粒问题

2015-08-10 14:42阅读:

棋盘放麦粒问题
棋盘放麦粒问题
经常使用算法之——多精度数的计算
end;
我们编程的计算机语言中有各种数的类型,但不管哪一个类型,其大小是定下的,这种类型的大小足够我们处理一般题目,但遇到数非凡大的情形,只有他们可就不灵了,怎么办呢?下面我们就来探讨一下这类算法。
program
WheatAndChess;
lenga,i,k:integer;
古印度国王要褒奖他的聪明能干的宰相达依尔(国际象棋的发明者),问他要什么。达依尔回答:“殿下只要在棋盘上第一个格子放一粒麦粒,在第二个格子放两粒,在第三个格子放四粒,以后的格子都是前一格的两倍。如此放满64格,我就心满足足了。”国王想,这不难办到。但一袋麦子很快就用完了,一仓库也用完了,全印度的麦子也远远不够。请编程计算所需的麦子总数。
上面两步完成仅仅是“1、算264的值”,还要要完成“2,将该值减1
首先将a1a最高位列位乘以2,还放在原来的数位上,这时得到的值就是上面讨论的0-19范围。
见到上面的题目,递推的方法还是我们的解题武器,既然第一格放一个表粒,第二格放两粒,第三格放四粒,以后的格子都是前一格的两倍,总的麦粒数就离不开下面的式子:
通过上面的竖式,我们不丢脸到,运算就是将各个数组乘以2,但还要注意因为各个数组是用来表示数位的,以是其值只能是处在09之间。
再化简一下,也就是264-1这么简单的题目是不会难倒任何人的,有六十四次循环不就处理了吗?
真地这么简单吗?如果真地编出了下面的程序,在执行的过程却遇到了题目:
program ChessWheat;
Var

begin
s:=1;

begin
s:=s*2;
write(s:10);
end;
end.
看看运行结果我们不难发现,这个程序算到16384时就结束了,16384正好是214次方!不是我们的计算程序有题目,而是由于我们放数的武器太小了,得到的结果放不开了!那如何才能放开结果呢?现有的语言的数据类型都不克不及直接处理这个题目,那就要想点其他的办法了,应用数组,重新模拟数的运算过程。

多精度数算法
我们可以大体估算一下,264这个数有多大?2101024,这个数大约后面有180,如何表达这个数呢,可以通过一个数组来放,数组设得足够大,a[25],用a[1]表示最低位个位,a[2]表示十位,依次类推。有了放数的工具,题目又出来了,如何运算呢?下一个很重要的任务是来模拟运算过程:
a[25]…a[2]a[1]
X 2
write(a[k]);
20+21+22+…263
模拟的过程我们可分成两步:
a[k+1]:=a[k+1]+1;
2、将上面的值减1
第一步费事一些,但其求的整体过程还是脱离不开我们上面用到的循环,需要改造的是s:=s*2这一句,将s通过数组a25-a1模仿,还要模拟乘以2的这种运算。
因为是乘以2,我们大体有个估算值,不考虑进位,每个位的值不大概超越18,以是如果有进位,向高位进位的值不超越1,加上进位值不超越19,为了方便,我们将乘以2的运算通过两步来完成:
begin
然后再根据a1a最高位各值的环境分别处理,使其符合十进制数的数字特点,妈保证列位上的数在0-9范围内,由于上面的计算得出的值大概有在10-18内的数,以是需从低位a1开端向a最高位高位方向搜索,如果值在10-19范围内,则给高一位的数组加上,同时本位只保留除以10后的余数。

此步很简单,分析得知2的任意次方的个位数只能大于2,以是直接用个位,即a1减去1就好了。
writeln('');
end;
源程序如下:

for i:=0 to 63 do
m:integer;
max=25;
var
a:array[1..max] of integer;
a[1]:=a[1]-1;
{取数字长度函数}
function lena(b:array of integer):integer;
var
const
begin
{计算数的长度}
for m:= max downto 1 do
begin
if a[m]<>0 then
begin
lena:=m;
break;
end;
end;



end;
for k:=1 to max do a[k]:=0;
a[1]:=1;
write('First for') ;
writeln('');
{算乘方}
if a[k]>=10 then
for k:=lena(a[max]) downto 1 do
1、算264的值;
end;

begin
for k:=1 to lena(a[max]) do
for k:=1 to lena(a[max]) do a[k]:=a[k]*2;
for i:=1 to 64 do
begin
a[k]:=a[k] mod 10;
write('a',i);

end;
{输出}

题目分析
begin
write(a[k]);
end;
writeln('');
begin

{1}
多精度算法解棋盘麦子
{输出}
i,s:integer;
for k:=lena(a[max]) downto 1 do
begin
_____________
write(':');

write('The final LENGTH',lena(a[max]));

end.
小结
推导的方式,循环的方式的确是我们解题的有力工具,但有时在推导时,不是说任意环境都硬套公式就一切OK,还要根据相应的特点,做出某些改变。涉及到精度很高的数时,模拟数的运算有时是一种必须的基本功,而今编程不是在高级的方面,而我们刚开端学习时的一些数学知识变得非常重要,因为电脑是比儿童要笨得多的工具!
(赵玉勇)
更多资讯请参考:huanyayule.in/

我的更多文章

下载客户端阅读体验更佳

APP专享