题目链接:点击打开链接;
题意:给定一个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;
}