题目链接:传送门
题意:
给定一个m个面的骰子然后给定两种询问,0 m n,表示求丢多少次使得最后丢的n次都相同的期望,1 m n表示求最后丢的n次两两不相同的期望。
分析:
设dp[i]表示已经有i个相同/不相同的到n个不相同的期望那么dp[n]很明显等于0。
连续n个相同:
dp[0] = 1 + dp[1],0的后继状态只可能出现1且概率为1.
dp[1] = 1 + dp[2]*(1/m) + dp[1]*(m-1)/m,1的后继状态只会有1,2两种情况概率分别为(m-1)/m,1/m;
...
dp[i] = 1 + dp[i+1]*(1/m) + dp[1]*(m-1)/m,i的后继状态也只有1,i+1两种情况概率分别为(m-1)/m,1/m;
dp[i+1] = 1 + dp[i+2]*(1/m) + dp[1]*(m-1)/m,i的后继状态也只有1,i+2两种情况概率分别为(m-1)/m,1/m;
...
dp[n] = 0;
设d[i] = dp[i] -dp[i+1] ,d[0]=1;
d[i] = 1/m * d[i+1]
d[0]+d[1]+...+d[n-1] = dp[0] - dp[n] = m^0 + m^1 +...+ m^(n-1)
连续n个不相同:
dp[0] = 1 + dp[1] 0的后继状态只有1这一种概率为1.
dp[1] = 1 + dp[1]*(1/m) + dp[2]*(m-1)/m; 1的后继状态有1,2,这两种情况概率为1/m,(m-1)/m;
dp[2] = 1 + (dp[1]+dp[2])*(1/m) + dp[3]*(m-2)/m;1的后继状态有1,2,3这三种情况概率为1/m,1/m,(m-2)/m;
...
dp[i] = 1 + (dp[1] + dp[2]+...+ dp[i])*(1/m) + dp[i+1]*(m-i)/m;1的后继状态有1,2,3,..i,i+1这i+1种情况概率为1/m,..,1/m,(m-i)/m;
dp[i+1] = 1 + (dp[1] + dp[2]+...+ dp[i]+dp[i+1])*(1/m) + dp[i+2]*(m-i-1)/m;1的后继状态有1,2,3,..i,i+1这i+1种情况概率为1/m,..,1/m,(m-i-1)/m;
...
dp[n]=0;
设d[i] = dp[i]-dp[i+1] = (m-i-1)/m*(dp[i+1]-dp[i+2) d[0]=1;
dp[0] + dp[n] = d[0] +d[2] +...+d[n-1] = m/(m-0) +m/(m-1)+...+m/(m-n+1)+m/(m-n);
代码如下:
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
double calc1(int m,int n){
double ans = 0;
for(int i=0;i<n;i++){
ans = ans+pow(m+0.0,i);
}
return ans;
}
double calc2(int m,int n){
double ans = 0;
double tmp = 1.0;
for(int i=1;i<=n;i++){
ans+=tmp;
tmp=tmp*m/(m-i);
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
int ord,n,m;
scanf("%d%d%d",&ord,&m,&n);
if(ord==0){
printf("%.7lf\n",calc1(m,n));
}
else{
printf("%.7lf\n",calc2(m,n));
}
}
return 0;
}