您的位置:首页 > 其它

TYVJ P1375 山洞历险

2015-10-31 07:48 423 查看

P1375 山洞历险

描述

小A在经历了和许多山头的一番大战后,总算拿到了最多的石子。他跌跌撞撞地来到了一个看上去比较隐蔽的山洞。让他惊奇的是,这个山洞里竟然摆满了美味佳肴,早已筋疲力尽饥肠辘辘的小A顺手抓了一个苹果咬了一口,他只觉得眼前一黑,便晕了过去……等他醒来时,发现自己被五花大绑,躺在一口大锅旁边。难道遇到了食人魔?小A大汗。
小A突然发现旁边的地上写着一行小字,“年轻人,恭喜你来到神奇山洞。如果你可以通过山洞,那么你将获得超人的rp,否则你将和很多人一样成为洞中的枯骨。按动你面前石锅左侧的按钮,它就可以随机变换图案,鲜花代表生机,骷髅则象征死亡,它们每次出现的可能性是相同的。如果连续两次出现鲜花,那你就可以挣脱绳子,通过山洞。”
小A的rp有限,在按动n次按钮后就会耗尽,如果此时他还未脱身,那他就over了。小A想请你帮忙计算当按了n次按钮时,他恰好能够脱身的几率。你能帮他吗?


输入输出 Input&Output

输入格式

一个正整数n

输出格式

第一行,整数a,表示所求概率的分母

第二行,整数b,表示所求概率的分子

样例 Sample

测试样例1

输入

2

输出

4

1

备注

第一次是鲜花的概率为1/2,第二次还是鲜花的概率为1/2,两次概率相乘为1/4。

对于30%的数据:n<=50

对于100%的数据:n<=32767

分析

可以看出分子是斐波那契数列,分母是2的幂次方。所以直接计算就可以了,斐波那契数列可以利用矩阵乘法加速转移。

代码如下

program cave;
const mp=100000000;
type  num=array[0..1600] of int64;
matrix=array[1..2,1..2] of num;
var k,i:longint;
f,t,sum:matrix;
fenmu,num3,two:num;
time:double;
procedure add(var num1,num2:num);
var i,len:longint;
begin
if num1[0]>num2[0]
then len:=num1[0]
else len:=num2[0];
for i:=1 to len do
begin
num1[i]:=num1[i]+num2[i];
num1[i+1]:=num1[i+1]+(num1[i] div mp);
num1[i]:=num1[i] mod mp;
end;
while num1[len+1]>0 do inc(len);
num1[0]:=len;
end;

procedure multiply(var num1,num2:num);
var i,j:longint;
begin
fillchar(num3,sizeof(num3),0);
for i:=1 to num1[0] do
for j:=1 to num2[0] do
begin
num3[i+j-1]:=num3[i+j-1]+(num1[i]*num2[j]);
num3[i+j]:=num3[i+j]+(num3[i+j-1]) div mp;
num3[i+j-1]:=num3[i+j-1] mod mp;
end;
num3[0]:=num1[0]+num2[0]+1;
while (num3[num3[0]]=0) and (num3[0]>0) do dec(num3[0]);
end;

procedure _matrix(var a,b:matrix;n,k,m:longint);
var c:matrix;
i,j,kx:longint;
begin
fillchar(c,sizeof(c),0);
for i:=1 to n do
for j:=1 to m do
for kx:=1 to k do
begin
multiply(a[i,kx],b[kx,j]);
add(c[i,j],num3);
end;
a:=c;
end;

procedure power(var t:matrix;k:longint);
begin
fillchar(sum,sizeof(sum),0);
sum:=t;
k:=k-1;
while k<>0 do
begin
if k and 1=1 then _matrix(sum,t,2,2,2);
k:=k>>1;
_matrix(t,t,2,2,2);
end;
t:=sum;
end;

procedure power2(a:num;b:longint);
var i:longint;
begin
fenmu:=a;
b:=b-1;
while b<>0 do
begin
if b and 1=1 then
begin multiply(fenmu,a);
fenmu:=num3;
end;
b:=b>>1;
multiply(a,a);
a:=num3;
end;
end;

procedure print(x:int64);
begin
if x<10 then write('0000000',x)
else if x<100 then write('000000',x)
else if x<1000 then write('00000',x)
else if x<10000 then write('0000',x)
else if x<100000 then write('000',x)
else if x<1000000 then write('00',x)
else if x<10000000 then write('0',x)
else if x<100000000 then write(x);
end;

begin
readln(k);
case k of
1:begin
write(0);
end;
2:begin
writeln(4);
write(1);
end;
3:begin
writeln(8);
write(1);
end;
4:begin
writeln(8);
write(1);
end
else
begin
k:=k-3;
fillchar(f,sizeof(f),0);
f[1,1][0]:=1;
f[1,1][1]:=1;
f[1,2][0]:=1;
f[1,2][1]:=2;
t[1,1][0]:=1;
t[1,1][1]:=0;
t[1,2][0]:=1;
t[1,2][1]:=1;
t[2,1][0]:=1;
t[2,1][1]:=1;
t[2,2][0]:=1;
t[2,2][1]:=1;
if k>=2 then
begin
power(t,k-1);
_matrix(f,t,1,2,2);
end;
two[0]:=1;
two[1]:=2;
power2(two,k+3);
write(fenmu[fenmu[0]]);
for i:=fenmu[0]-1 downto 1 do
print(fenmu[i]);
writeln;
write(f[1,2][f[1,2][0]]);
for i:=f[1,2][0]-1 downto 1 do
print(f[1,2][i]);
end;
end;
end.


评测结果

#0: Accepted (0ms, 1164KiB)

#1: Accepted (0ms, 1208KiB)

#2: Accepted (0ms, 1208KiB)

#3: Accepted (0ms, 1204KiB)

#4: Accepted (15ms, 1208KiB)

#5: Accepted (46ms, 1208KiB)

#6: Accepted (78ms, 1204KiB)

#7: Accepted (93ms, 1208KiB)

#8: Accepted (265ms, 1208KiB)

#9: Accepted (312ms, 1208KiB)


Hold On

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息