传球

问题描述:
N个人坐成一圈, 其中第K个人拿着一个球。 每次每个人会以一定的概率向
左边的人和右边的人传球。 当所有人都拿到过球之后, 最后一个拿到球的人即为胜者。 求第N个人获胜的概率。( 所有人按照编号逆时针坐成一圈)
输入格式:
第一行一个数T代表数据组数。
对于每组数据, 第一行两个整数N, K如题意所述。
接下来每行一个实数p代表该人将球传给右边的人的概率。
输出格式:
对于每组数据, 一行一个实数代表答案, 保留9位小数。
样例输入:
1
5 1
0.10
0.20
0.30
0.40
0.50
样例输出:
0.007692308
数据规模与约定:
对于20%的数据, N ≤ 3。
对于70%的数据, T, N ≤ 100。
对于100%的数据, T ≤ 10000,1 ≤ N ≤ 100。

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=110;
int t,n,k,pre[maxn],next[maxn];
long double l[maxn],r[maxn];
void deal(int b)
{
int a=pre[b],c=next[b];
long double ra=r[a]*r[b]/(1-r[a]*(1-r[b]));
long double lc=(1-r[c])*(1-r[b])/(1-(1-r[c])*r[b]);
r[a]=ra;l[a]=1-r[a];l[c]=lc;r[c]=1-l[c];
next[a]=c;pre[c]=a;
}
long double work()
{
if(n<=2) return 1;
if(n<=3) return k==1 ? r[1]:l[2];
for(int i=1;i<=n;i++)
pre[i]=i-1,next[i]=i+1;
pre[1]=n;next[n]=1;
if(k==1)
{
for(int i=2;i<n-1;i++)
deal(i);
return r[1];
}
if(k==n-1)
{
for(int i=2;i<n-1;i++)
deal(i);
return l[n-1];
}
for(int i=2;i<k;i++)
deal(i);
for(int i=k+1;i<n-1;i++)
deal(i);
deal(k);
return l[k]*r[1]+r[k]*l[n-1];
}
int main()
{
freopen("it.in","r",stdin);
freopen("it.out","w",stdout);
cin>>t;
while(t--)
{
cin>>n>>k;
for(int i=1;i<=n;i++)
{
double x;
scanf("%lf",&x);
r[i]=x;
l[i]=1-r[i];
}
printf("%0.9lf\n",(double)work());
}
fclose(stdin);fclose(stdout);
return 0;
}