noi99钉子和小球 解题报告

题目叙述

钉子和小球
Time Limit: 1000MS Memory Limit: 10000K

题目描述

有一个三角形木板,竖直立放,上面钉着n(n + 1) / 2颗钉子,还有(n + 1)个格子(当n = 5时如图1)。每颗钉子和周围的钉子的距离都等于d,每个格子的宽度也都等于d,且除了最左端和最右端的格子外每个格子都正对着最下面一排钉子的间隙。 让一个直径略小于d的小球中心正对着最上面的钉子在板上自由滚落,小球每碰到一个钉子都可能落向左边或右边(概率各1/2),且球的中心还会正对着下一颗将要碰上的钉子。例如图2就是小球一条可能的路径。 我们知道小球落在第i个格子中的概率pi=,其中i为格子的编号,从左至右依次为0, 1, ..., n。现在的问题是计算拔掉某些钉子后,小球落在编号为m的格子中的概率pm。假定最下面一排钉子不会被拔掉。例如图3是某些钉子被拔掉后小球一条可能的路径。

输入描述

第1行为整数n(2 ≤ n ≤ 50)和m(0 ≤ mn)。以下n行依次为木板上从上至下n行钉子的信息,每行中'*'表示钉子还在,'.'表示钉子被拔去,注意在这n行中空格符可能出现在任何位置。

输出描述

仅一行,是一个既约分数(0写成0/1),为小球落在编号为m的格子中的概率pm。既约分数的定义:A/B是既约分数,当且仅当A, B为正整数且AB没有大于1的公因子。

样例输入

5 2
    *
   * .
  * * *
 * . * *
* * * * *

样例输出

7/16

这题真的做的人吐血.....本来DP已经写的够小心了,还要弄个高精才过的了...唉呀,不管了

只要注意细节,就可以通过.....

1.题目给出的是钉子的位置,但是我们要用到的空格,切每次球通过的路径是钉子间的空隙,所以要相应的处理下。本人采用的是map[i,j]储存的是(i,j)位置钉子的情况,f[i-1,j]储存的是钉子(i,j)的通过的球的情况。

2.动态方程如下:

 f[i+1,j]:=f[i,j]+f[i+1,j];f[i+1,j+1]:=f[i,j]+f[i+1,j+1]; (if map[i,j]='*')

   f[i+2,j+1]:=f[i,j]*4+f[i+2,j+1];(if map[i,j]='.')

3.记得加高精!

代码如下:

 

  1 const acc=10000;
  2 type
  3     arra=record
  4                da:array[0..30]of longint;
  5                l:longint;
  6     end;
  7 var i,j,n,m,q:longint;
  8     map:array[0..50,0..50]of char;
  9     f:array[0..60,0..60]of arra;
 10     ch:char;
 11     fm,t,z:arra;
 12 function add(a,b:arra):arra;
 13 var
 14    c:arra;i:longint;
 15 begin
 16      fillchar(c,sizeof(c),0);
 17      if a.l>b.l then c.l:=a.l else c.l:=b.l;
 18      for i:=1 to c.l do
 19          begin
 20               c.da[i]:=c.da[i]+a.da[i]+b.da[i];
 21               if c.da[i]>=acc then
 22                  begin
 23                       inc(c.da[i+1]);
 24                       c.da[i]:=c.da[i] mod acc;
 25                  end;
 26          end;
 27      if c.da[c.l+1]>0 then inc(c.l);
 28      add:=c;
 29 end;
 30 procedure mult2(var a:arra);
 31 var i,k:longint;b:arra;
 32 begin
 33      k:=0;
 34      fillchar(b,sizeof(b),0);
 35      b.l:=a.l;
 36      for i:=1 to a.l do
 37          begin
 38               b.da[i]:=b.da[i]+a.da[i]*2;
 39               if b.da[i]>=acc then
 40                  begin
 41                       b.da[i]:=b.da[i] mod acc;
 42                       inc(b.da[i+1]);
 43                  end;
 44          end;
 45      if b.da[b.l+1]<>0 then inc(b.l);
 46      a:=b;
 47 end;
 48 procedure divid2(var a:arra);
 49 var i,k,t:longint;b:arra;
 50 begin
 51      k:=0;
 52      fillchar(b,sizeof(b),0);
 53      b.l:=a.l;
 54      for i:= a.l downto 1 do
 55          begin
 56               k:=k*acc+a.da[i];
 57               if k>=2 then
 58                  begin
 59                       t:=k shr 1;
 60                       b.da[i]:=t;
 61                       k:=k-(t shl 1);
 62                  end;
 63          end;
 64      a:=b;
 65      while (a.da[a.l]=0)and(a.l>1do dec(a.l);
 66 end;
 67 procedure print(a:arra);
 68 var i:longint;s:string;
 69 begin
 70      write(a.da[a.l]);
 71      for i:=a.l-1 downto 1 do
 72          begin
 73               str(a.da[i]+acc,s);
 74               delete(s,1,1);
 75               write(s);
 76          end;
 77 end;
 78 begin
 79      
 80      readln(n,m);
 81      fillchar(f,sizeof(f),0);
 82      f[0,1].da[1]:=1;f[0,1].l:=1;
 83      for i:=1 to n do
 84          begin
 85               for j:=1 to i do
 86                   begin
 87                        read(ch);
 88                        while (ch<>'*')and(ch<>'.'do read(ch);
 89                        map[i,j]:=ch;
 90                   end;
 91               readln;
 92          end;
 93      for i:=0 to n-1 do
 94          begin
 95               for j:=1 to i+1 do
 96                   begin
 97                        if map[i+1,j]='*' then
 98                           begin
 99                                f[i+1,j]:=add(f[i,j],f[i+1,j]);
100                                f[i+1,j+1]:=add(f[i,j],f[i+1,j+1]);
101                           end
102                        else
103                            begin
104                                 z:=add(f[i,j],f[i,j]);
105                                 z:=add(z,z);
106                                 f[i+2,j+1]:=add(z,f[i+2,j+1]);
107                            end;
108                   end;
109          end;
110     t:=f[n,m+1];
111     if (t.l=1)and(t.da[1]=0then writeln('0/1')
112     else
113         begin
114              q:=n;
115              while not(odd(t.da[1])) and not((t.l=0)and(t.da[1]=0)) do
116                    begin
117                         divid2(t);
118                         dec(q);
119                    end;
120              fillchar(fm,sizeof(fm),0);
121              fm.da[1]:=1;fm.l:=1;
122              for i:=1 to q do mult2(fm);
123              print(t);write('/');print(fm);writeln;
124         end;
125 end.

 

posted @ 2009-11-10 15:56  瀑布飞鹰  阅读(340)  评论(0编辑  收藏  举报