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