| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 4090 | Accepted: 1050 |
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
Source
对于每一段,通过该段的概率等于1-踩到该段终点的地雷的概率。
就比如第一段 1~x[1]. 通过该段其实就相当于是到达x[1]+1点。那么p[x[1]+1]=1-p[x[1]].
但是这个前提是p[1]=1,即起点的概率等于1.对于后面的段我们也是一样的假设,这样就乘起来就是答案了。
对于每一段的概率的求法可以通过矩阵乘法快速求出来。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
double p;
double num[2][2];
void fun(int x)
{
int i,j,k;
double cnt[2][2]={p,1.0-p,1.0,0.0},tmp[2][2];
num[0][0]=num[1][1]=1.0;
num[0][1]=num[1][0]=0.0;
while(x>0)
{
if(x&1)
{
for(i=0;i<2;i++)
for(j=0;j<2;j++)
{
tmp[i][j]=num[i][j];
num[i][j]=0.0;
}
for(i=0;i<2;i++)
for(j=0;j<2;j++)
for(k=0;k<2;k++)
num[i][j]+=tmp[i][k]*cnt[k][j];
}
for(i=0;i<2;i++)
for(j=0;j<2;j++)
{
tmp[i][j]=cnt[i][j];
cnt[i][j]=0.0;
}
for(i=0;i<2;i++)
for(j=0;j<2;j++)
for(k=0;k<2;k++)
cnt[i][j]+=tmp[i][k]*tmp[k][j];
x>>=1;
}
return ;
}
int main()
{
int N,i,cur,flag;
int X[100]={-100};
double d[10];
double ans;
while(scanf("%d%lf",&N,&p)==2)
{
for(i=1;i<=N;i++)
scanf("%d",&X[i]);
sort(X+1,X+1+N);
if(X[1]==1)
{
printf("0.0000000\n");
continue;
}
flag=0;
for(i=1;i<N;i++)
if(X[i]+1==X[i+1])
{
flag=1;
printf("0.0000000\n");
break;
}
if(flag)
continue;
ans=1.0;
cur=1;
for(i=1;i<=N;i++)
{
d[1]=1.0; d[2]=p;
if(X[i]-cur==1)
{
ans*=(1-d[2]);
cur=X[i]+1;
continue;
}
fun(X[i]-cur-1);
d[3]=num[0][0]*d[2]+num[0][1]*d[1];
ans*=(1-d[3]);
cur=X[i]+1;
}
printf("%.7lf\n",ans);
}
return 0;
}
1123




被折叠的 条评论
为什么被折叠?



