题目描述
n个人排成一排,你排在第m个。每轮队首的人投一次骰子:
若掷到1,则队首的人获胜;
若掷到2,4,6,则队首的人出队;
若掷到3,5,则队首的人排到队尾。
获胜者仅有一人,若队列中仅剩一人,则该人获胜。求你获胜的概率。
输入输出格式
输入格式:
一行两个整数n,m
输出格式:
一个实数表示获胜概率(精确到小数点后9位)
输入输出样例
输入样例#1: 复制
2 1
输出样例#1: 复制
0.375000000
说明
【数据范围】
对于30%的数据:n<=10
n个人排成一排,你排在第m个。每轮队首的人投一次骰子:
若掷到1,则队首的人获胜;
若掷到2,4,6,则队首的人出队;
若掷到3,5,则队首的人排到队尾。
获胜者仅有一人,若队列中仅剩一人,则该人获胜。求你获胜的概率。
输入输出格式
输入格式:
一行两个整数n,m
输出格式:
一个实数表示获胜概率(精确到小数点后9位)
输入输出样例
输入样例#1: 复制
2 1
输出样例#1: 复制
0.375000000
说明
【数据范围】
对于30%的数据:n<=10
对于100%的数据:n<=1000,m<=n
做了击倒概率题目后,做这个题目发现不会做。想了半天,花了个搜索树,做出了样例数据:0.375.
1,2
1/6 :1赢 1/2 1输 :2 1/3: 2,1
1/6:2赢 1/2 1赢 1/3 :1,2
所以:f(1)=1/6+1/3 * 1/2+ 1/3 *1/3 *f(1)
=>f(1)=1/3 / 8/9=3/8=0.375.
但是已经ac的题目用的题目数据为:
若掷到1,则队首的人获胜;
若掷到2,4,6,则队首的人到队尾;
若掷到3,5,则队首的人出队。
画出的状态转移图为:
参考代码:
#include <iostream>
#include<cstdio>
#include <cmath>
using namespace std;
double f[2000][2000];
int main()
{
int n,m;
cin>>n>>m;
f[1][1]=double(1);
for(int i=2;i<=n;++i){
f[i][1]=1.0/6.0;
for(int j=i-1;i-j<=60&&j>=1;--j){
f[i][1]+=f[i-1][j]/(1LL<<(i-j))/3;
// cout<<i-1<<" "<<j<<" "<<f[i][1]<<endl;
}
if(i<=60)f[i][1]/=((1LL<<i)-1)/(double)(1LL<<i);
// cout<<f[i][1]<<endl;
for(int j=2;j<=i;++j)
f[i][j]=f[i-1][j-1]/3+f[i][j-1]/2;
}
printf("%0.9f",f[n][m]);
return 0;
}