TYVJ P1375 山洞历险

来源:互联网 发布:王者荣耀淘宝充值封号 编辑:程序博客网 时间:2024/04/28 02:20

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

0 0
原创粉丝点击