POJ 3744 Scout YYF

来源:互联网 发布:网络大电影 知乎 编辑:程序博客网 时间:2024/06/11 03:30

Description

YYF is a couragous scout. Now he is on a dangerous mission which is to penetrate into the enemy's base. After overcoming a series difficulties, YYF is now at the start of enemy's famous "mine road". This is a very long road, on which there are numbers of mines. At first, YYF is at step one. For each step after that, YYF will walk one step with a probability of p, or jump two step with a probality of 1- p. Here is the task, given the place of each mine, please calculate the probality that YYF can go through the "mine road" safely.

Input

The input contains many test cases ended with EOF.
Each test case contains two lines.
The First line of each test case is N (1 ≤ N ≤ 10) and p (0.25 ≤ p ≤ 0.75) seperated by a single blank, standing for the number of mines and the probability to walk one step.
The Second line of each test case is N integer standing for the place of N mines. Each integer is in the range of [1, 100000000].

Output

For each test case, output the probabilty in a single line with the precision to 7 digits after the decimal point.

Sample Input
1 0.5
2
2 0.5
2 4
Sample Output

0.5000000
0.2500000

10个雷,1亿的范围,明显不能线性递推。

于是就想到矩阵快速幂。没去翻模版,就直接写了简单的二阶矩阵快速幂;

struct A{double a[2][2];A power(int n){if(n==1) return *this;if(n==2) return *this*(*this);A C=power(n>>1);if(n&1){return *this*C.power(2);}else{return C.power(2);}}A operator *(const A &B){A C;C.a[0][0]=a[0][0]*B.a[0][0]+a[0][1]*B.a[1][0];C.a[0][1]=a[0][0]*B.a[0][1]+a[0][1]*B.a[1][1];C.a[1][0]=a[1][0]*B.a[0][0]+a[1][1]*B.a[1][0];C.a[1][1]=a[1][0]*B.a[0][1]+a[1][1]*B.a[1][1];return C;}};
然后递推关系有两种,若n是雷,则p[n]=0;

先令最后一个雷的右边的概率都是1;因为已经没危险了。所以初始数对是(1,1)

令数对为(t1,t2); 若n是雷,则 应该是 0 t1 t2   即  (  t1  ,  t2  )*某矩阵=(  0 , t1  )  这个矩阵记为M。

若n不是雷,则 (t1,t2)*某矩阵=(  p*t1  ,  (1-p) * t2  )   这个矩阵记为 I。

A I;I.a[0][0]=p;I.a[0][1]=1;I.a[1][0]=1-p;I.a[1][1]=0;A M;M.a[0][0]=0;M.a[0][1]=1;M.a[1][0]=0;M.a[1][1]=0; 

接下来,从大往小,遇到雷就乘M,不是雷就乘I。然后就好了。

A ANSA; //初始化答案的矩阵ANSA.a[0][0]=1;ANSA.a[0][0]=0;ANSA.a[0][0]=0;ANSA.a[0][0]=1;for(int i=n-1;i>0;i--){ANSA=ANSA*M*I.power(mine[i]-mine[i-1]-1);//每次计算雷+后面的空白之间的矩阵。mine数组用来存雷的位置。mine用之前已排序。}
ANSA=ANSA*M*I.power(mine[0]-1);
ANS=ANSA.a[0][0]+ANSA.a[1][0];//这一步模拟(1,1)*矩阵ANSA 的结果,取左边的一位。就是答案。

printf("%.7lf\n",ANS);//开始用的%.7lf  结果  WA  了。//查了半天题解,然后把  %.7lf  改成  %.7f 就过了~




0 0