Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 6763 | Accepted: 1966 |
Description
Input
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
Sample Input
1 0.5 2 2 0.5 2 4
Sample Output
0.5000000 0.2500000
题意是Scout这个人一开始站在位置1处。然后他向前走一步的概率是p,向前走两步的概率是1-p。然后给出一些位置上面有地雷,问Scout安全通过,即这里面的地雷一个都没有踩到的概率是多少。
首先肯定是有x[i]=p*x[i-1]+(1-p)*x[i-2],因为地雷的范围比较大,所以要构造矩阵来做,转移矩阵就是
p 1-p
1 0
乘以矩阵a[i] a[i-1](竖着写。。。)就等于a[i+1] a[i](还是竖着写。。。)
接下来自己又遇到问题了,就算这个矩阵搞出来了,结果还是不知道怎么算。。。
后来自己这样想的,Scout安全通过,就是通过了所有的地雷,首先算通过地雷1的概率,即没有踩到地雷1,盖罗威是p1,然后发现如果安全通过地雷1,那么此时Scout一定站在地雷1 x[1]的后面的那个位置,即x[1]+1,然后开始算地雷2的概率。所以呢,按照我自己的理解,相互之间的地雷本身在算概率的时候是没有直接关系的,前一个地雷只是在算的时候给你提供了一个起始位置。(如有不同意见,随时欢迎拍砖。。。)
搞懂这里,接下来就很好出了。。。
将地雷位置按大小排好序后,x[1] x[2] x[3] ...x[n],然后每一段转移矩阵转了x[i]-x[i-1]-1次,因为一开始的a[i] a[i-1]一直都是 1 0。(因为只要成功通过地雷n,那么此时Scout就一定站在x[n]+1)。所以直接取结果的matrix[0][0]就是Scout踩到地雷的概率p,1-p就是没有踩到这个地雷的概率。
结果就是乘以每一个没有踩到地雷的概率。
代码:
#pragma warning(disable:4996)
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <deque>
#include <ctime>;
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define INF 0x3fffffff
#define REP(i, n) for (int i=0;i<n;++i)
#define REP1(i, n) for (int i=1;i<=n;++i)
const ll mod = 1e9 + 7;
const int maxn = 2;
int n, num[20];
double p;
struct Matrix
{
double mat[maxn][maxn];
Matrix()
{
memset(mat, 0, sizeof(mat));
}
void clear() { memset(mat, 0, sizeof(mat)); }
friend Matrix operator *(const Matrix &A, const Matrix &B);
friend Matrix operator ^(Matrix A, int n);
};
Matrix operator *(const Matrix &A, const Matrix &B)
{
Matrix ret;
for (int i = 0; i < maxn; i++)
{
for (int j = 0; j < maxn; j++)
{
for (int k = 0; k < maxn; k++)
{
ret.mat[i][j] = ret.mat[i][j] + (A.mat[i][k] * B.mat[k][j]);
}
}
}
return ret;
}
Matrix operator ^(Matrix A, int n)
{
Matrix ret;
for (int i = 0; i < maxn; i++)
{
ret.mat[i][i] = 1;
}
for (; n; n >>= 1, A = A*A)
if (n & 1)
ret = ret*A;
return ret;
}
void input()
{
REP1(i, n)
{
scanf("%d", &num[i]);
}
sort(num + 1, num + n + 1);
}
void solve()
{
if (num[1] == 1)
{
puts("0.0000000");
return;
}
Matrix res1, res2;
res2.mat[0][0] = p;
res2.mat[0][1] = 1 - p;
res2.mat[1][0] = 1;
res2.mat[1][1] = 0;
double ans = 1;
REP1(i, n)
{
if (num[i] == num[i - 1])continue;
res1 = (res2 ^ (num[i] - num[i - 1] - 1));
ans = ans*(1 - res1.mat[0][0]);
}
printf("%.7f\n", ans);
}
int main()
{
//freopen("i.txt", "r", stdin);
//freopen("o.txt", "w", stdout);
while (scanf("%d%lf", &n, &p) != EOF)
{
input();
solve();
}
return 0;
}