您的位置:首页 > 其它

noip2002-麦森数 2008.11.4

2016-02-05 11:32 330 查看
noip2002-麦森数 2008.11.4

心得:在变程序前,一定要对题目进行彻底的分析,为了减少时间,就要减少机器的运算次数,要抓住特点进行转化。例如这道题:2^p转化为高精度乘高精度和高精度乘单精度,先平方,再根据余数进行乘法计算。

先乘方,就减小了加法和单精度乘法的运算次数。

Program1:赤裸裸的模拟—超时5组

program mason;
const fin='mason.in';fout='mason.out';
k=10000000000;k1=10;
type arr=array[0..51]of int64;
var f1,f2:text;
p,i,j,m,l,xx:longint;
s:arr;
ss:string;
procedure add;
var i:longint;y:arr;
begin
fillchar(y,sizeof(y),0);
for i:=1 to m do
begin
y[i]:=s[i]+s[i]+y[i];
y[i+1]:=y[i] div k+y[i+1];
y[i]:=y[i] mod k;
end;
if y[m+1]<>0 then inc(m);
if m>50 then m:=51;
s:=y;
end;

begin
assign(f1,fin);reset(f1);
assign(f2,fout);rewrite(f2);
read(f1,p);
fillchar(s,sizeof(s),0);
s[0]:=1;
s[1]:=2;m:=1;
for i:=1 to p-1 do
add;
s[1]:=s[1]-1;
j:=1;
while s[j]<0 do
begin
s[j]:=s[j]+k;
inc(j);
s[j]:=s[j]-1;
end;
xx:=0;
str(s[m],ss);
l:=length(ss);
writeln(f2,trunc(p*(ln(2)/ln(10)))+1);
for i:=50 downto 1 do
begin inc(xx);
str(s[i],ss);
for j:=1 to k1-length(ss) do
write(f2,0);
write(f2,s[i]);
if xx mod 5=0 then writeln(f2);
end;
close(f1);close(f2);
end.<span style="color:#3366ff;">
</span>


Program2:改进预算方法:可以确定位数为trunc(p*lg(2)/lg(10)+1);
然后,将P转化为二进制数,定义两个过程,分别为高精度乘高精度和高精度乘单精度,先平方,再
根据余数进行乘法计算,若余数为1就乘2;
最后,输出后500位,并把末位减1就行了.
program mason;
type
arraytype=array [1..2000] of longint;
var
ans,binary:arraytype;
s,i,len,j,p,temp:longint;
procedure djgj;
var
x,i:longint;
begin
x:=0;
for i:=1 to 500 do
begin
x:=x+ans[i]*2;
ans[i]:=x mod 10;
x:=x div 10;
end;
end;
procedure gjgj;
var
i,j:longint;
x:longint;
ans1:arraytype;
begin
fillchar(ans1,sizeof(ans1),0);
for i:=1 to 500 do
begin
x:=0;
for j:=1 to 500 do
begin
x:=ans[i]*ans[j]+x div 10+ans1[i+j-1];
ans1[i+j-1]:=x mod 10;
end;
ans1[i+j]:=x div 10;
end;
ans:=ans1;
end;
begin
assign(input,'mason.in');reset(input);
assign(output,'mason.out');rewrite(output);
fillchar(ans,sizeof(ans),0);
readln(p);
len:=0;temp:=p;
while temp<>0 do
begin
len:=len+1;
binary[len]:=temp mod 2;
temp:=temp div 2;
end;//这里是精华部分!
ans[1]:=1;
for i:=len downto 1 do
begin
gjgj;
if binary[i]=1 then djgj;
end;
s:=trunc(p*(ln(2)/ln(10)))+1;
writeln(s);
ans[1]:=ans[1]-1;
for i:=500 downto 1 do
begin
write(ans[i]);
if i mod 50=1 then writeln;
end;
close(input);close(output);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: