来写一个概率dp专题
light oj 1027
有n个门让你选,每个门有一个数字,正数代表x分钟后出去,负数代表x分钟后回到起点重新开始
然后问你出去的时间期望是多少分钟
如果是一个正数,那么x分钟后就可以出去,如果是一个负数,那么等x分钟后,继续回到起点,那么答案就是
ans = (正数的个数 / 总个数) * (正数的和 / 正数的个数) + (负数的个数 / 总个数) * (负数的和 / 负数的个数 + ans)
化简后 ans = 总和(abs(x)) / (总个数 - 负数的个数)
int main(){
int t;
cin>>t;
for(int ii=1;ii<=t;ii++){
printf("Case %d: ",ii);
int n,x,sum=0,num=0;
cin>>n;
for(int i=0;i<n;i++){
cin>>x;
if(x<0){
num++;
}
sum+=abs(x);
}
if(num==n) printf("inf\n");
else {
int a=sum,b=n-num;
printf("%d/%d\n",a/__gcd(a,b),b/__gcd(a,b));
}
}
return 0;
}
light oj 1030
飞行棋,然后每个位置上有一个数字,6面骰子,问你从1走到n,走过的数的和的期望
概率dp求期望,倒着dp,dp[i]表示从i走到n的期望,因为你从i走到i+1,i+2,。。。i+6,i有1/6的概率转移到比如i+1,然后得到dp[i+1],所以dp[i]+=1/6(dp[i+1]+dp[i+2]+...+dp[i+6])。如果不满6格不一定是1/6
double dp[110];
int main(){
int t;
cin>>t;
for(int ii=1;ii<=t;ii++){
printf("Case %d: ",ii);
int n,x,sum=0,num=0;
cin>>n;
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++){
cin>>dp[i];
}
for(int i=n-1;i>=1;i--){
if(n-i<6){
for(int j=i+1;j<=n;j++){
dp[i]=dp[i]+dp[j]*1.0/(n-i);
}
}
else {
for(int j=i+1;j<=i+6;j++){
dp[i]=dp[i]+dp[j]*1.0/6;
}
}
}
printf("%.6f\n",dp[1]);
}
return 0;
}
lightoj 1038
给你一个数n,然后从他的因子中选择一个d,然后得到n/d,然后还是这样操作,问你得到1需要的次数的期望
首先就能想到,只跟因子的个数有关,然后就犯了一个小错
正确的是,dp[i] = 求和((1 / sum) * (1 + dp[j])) (sum是i所有的因子的个数,j是i的所有的因子)
化简后 dp[i] = ( 求和(dp[I/j]]) + i因子的个数 ) / (i因子的个数 - 1)
double dp[110000];
void init(){
memset(dp,0,sizeof(dp));
for(int i=2;i<=100002;i++){
double sum=0;
int temp=0;
for(int j=1;j*j<=i;j++){
if(i%j==0){
sum+=dp[j];
temp++;
if(j*j!=i){
sum+=dp[i/j];
temp++;
}
}
}
dp[i]=(sum+temp)*1.0/(temp-1);
}
}
int main(){
int t,n;
init();
cin>>t;
for(int ii=1;ii<=t;ii++){
cin>>n;
printf("Case %d: %.7f\n",ii,dp[n]);
}
return 0;
}
codeforces 148d
题意:袋子里有w白,b黑,龙和王妃轮流抓,谁先抓到白谁赢,王妃每次抓一只,龙每次抓完一只,跑出去一只,全部都是随机,没人抓到白龙赢,问王妃赢的概率
题解:dp[i][j]表示i白j黑的时候,王妃赢的概率
显然dp[i][0] =1, dp[0][i] = 0
double dp[1010][1010];
int main() {
int a,b;
cin>>a>>b;
memset(dp,0,sizeof(dp));
for(int i=1;i<=a;i++)
dp[i][0]=1;
for(int i=1;i<=a;i++){
for(int j=1;j<=b;j++){
///直接取到白的概率
dp[i][j]=i*1.0/(i+j);
///王妃取到黑,龙取到黑,跑出去一只黑
if(j>=3){
dp[i][j]+=j*1.0/(i+j)*(j-1)*1.0/(i+j-1)*(j-2)*1.0/(i+j-2)*dp[i][j-3];
}
///王妃取到黑,龙取到黑,跑出去一只白
if(j>=2){
dp[i][j]+=j*1.0/(i+j)*(j-1)*1.0/(i+j-1)*i*1.0/(i+j-2)*dp[i-1][j-2];
}
}
}
printf("%.10f\n",dp[a][b]);
return 0;
}