【CodeVS2885】钉子与小球

【Description】

  有一个三角形木板,竖直立放,上面钉着n(n+1)/2颗钉子,还有(n+1)个格子(当n=5时如图1)。每颗钉子和周围的钉子的距离都等于d,每个格子的宽度也都等于d,且除了最左端和最右端的格子外每个格子都正对着最下面一排钉子的间隙。

  让一个直径略小于d的小球中心正对着最上面的钉子在板上自由滚落,小球每碰到一个钉子都可能落向左边或右边(概率各1/2),且球的中心还会正对着下一颗将要碰上的钉子。例如图2就是小球一条可能的路径。

  现在的问题是计算拔掉某些钉子后,小球落在编号为m的格子中的概率pm。假定最下面一排钉子不会被拔掉。例如图3是某些钉子被拔掉后小球一条可能的路径。
  


【Input】

  第1行为整数n(2<=n<=50)。

  以下n行依次为木板上从上至下n行钉子的信息,每行中‘*’表示钉子还在,‘.’ 表示钉子被拔去(最下面一排的钉子不会拔掉),注意在这n行中空格符可能出现在任何位置。


【Output】

  共n+1行,每一行是一个既约分数(0写成0/1),为小球落在编号为0到编号为n这n+1个的格子中的概率m。

  既约分数的定义:A/B是既约分数,当且仅当A、B为正整数且A和B没有大于1的公因子。


【Sample Input】

4
*
* *
* . *
* * * *

【Sample Output】

1/16
1/8
5/8
1/8
1/16

【题解】

  动态转移方程:
  

f(i,j)=f(i,j)+f(i1,j1)2f(i,j)+f(i1,j)2 f(i,j)+f(i2,j1)i1j1i1 j i2j1.

  (另:pascal在计算 2n 时,如果变量类型为 int64 ,使用左移操作易出错)
  
  参考代码如下:

var c:char;
    f:array[0..52,0..52] of int64;
    i,j,n:longint;
    tmp,t:int64;
begin
  readln(n); t:=1;
  for i:=1 to n do t:=t*2; f[1,1]:=t;  //初始化
  for i:=1 to n do begin
    for j:=1 to i do begin
      read(c); while (c=' ') do read(c);  //处理空格
      if c='*' then begin
        inc(f[i+1,j],f[i,j] shr 1); inc(f[i+1,j+1],f[i,j] shr 1);
      end
      else inc(f[i+2,j+1],f[i,j]);
    end;
    readln;
  end;
  for i:=1 to n+1 do
    if f[n+1,i]=0  //分类输出
      then writeln('0/1')
      else begin
        tmp:=t;
        while (f[n+1,i] mod 2=0) do begin
          f[n+1,i]:=f[n+1,i] shr 1; tmp:=tmp shr 1;
        end;
        writeln(f[n+1,i],'/',tmp);
      end;
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值