題目鏈接:點擊打開鏈接;
題意:給定一個m個面的骰子然後給定兩種詢問,0 m n,表示求丟多少次使得最後丟的n次都相同的期望,1 m n表示求最後丟的n次兩兩不相同的期望。;
題目分析:
我們設dp[i]爲當前爲i個連續的數還需投擲次數的期望搭dp[0]就是解
在相同的情況:
dp[i] 記錄的是已經連續i個相同,到n個不同需要的次數的數學期望
dp[0]= 1+dp[1]
dp[1]= 1+( 1/m*dp[2]+(m-1)/m*dp[1])=1+(dp[2]+(1-m)*dp[1])/m;
dp[2]= 1+(dp[3]+(1-m)*dp[1])/m;
....................
dp[n]= 0
可以推出dp[i] = 1 + ( (m-1)*dp[1] + dp[i+1] ) / m,dp[i+1] = 1 + ( (m-1)*dp[1] + dp[i+2] ) / m;
我們不難看出這是等比數列:dp[0]=(1-m^n)/(1-m);
然而求不同的時候:
dp[0] = 1 + dp[1]
dp[1] = 1 + (dp[1] + (m-1) dp[2]) / m
dp[2] = 1 + (dp[1] + dp[2] + (m-2) dp[3]) / m
dp[i] = 1 + (dp[1] + dp[2] + ... dp[i] + (m-i)*dp[i+1]) / m
dp[i+1]= 1 + (dp[1] + dp[2] + ... dp[i] + dp[i+1] + (m-i-1)*dp[i+1]) / m
...
dp[n] = 0;
解得:dp[i] - dp[i+1] = (m-i-1)/m * (dp[i+1] - dp[i+2]);
因此:dp[0]-dp[1]=1;
dp[1]-dp[2]=1*m/(m-1);
dp[2]-dp[3]=1*m/(m-1)*m/(m-2);
..........
dp[n-1]-dp[n]=1*m/(m-1)*m/(m-2)*.......*m/(m-n+1);
累加起來就是答案
代碼如下:
#include <set>
#include <queue>
#include <math.h>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <algorithm>
using namespace std;
int main(){
int t;
while(scanf("%d",&t)!=EOF){
int x,n,m;
while(t--){
scanf("%d%d%d",&x,&n,&m);
if(!(x&1)){
double ans=0;
for(int i=0;i<m;i++)
ans+=pow(n+0.0,i);
printf("%.9f\n",ans);//爲0的時候就是等比數列前n項和
}
else{
double ans=0;
double tmp=1.0;
for(int i=1;i<=m;i++){
ans+=tmp;
tmp=tmp*n/(n-i);
}//爲1的時候就如我上述所說
printf("%.9f\n",ans);
}
}
}
return 0;
}