当前位置: 代码迷 >> 综合 >> HDU4652 Dice(期望dp推式子)
  详细解决方案

HDU4652 Dice(期望dp推式子)

热度:78   发布时间:2024-02-27 20:30:51.0

题目链接

第一问,求连续nnn个数字相同的期望

定义dp[i]dp[i]dp[i]是已经iii个不相同,到达目标状态的期望

dp[n?1]=1m?dp[n]+m?1m?dp[1]+1dp[n-1]=\frac{1}{m}*dp[n]+\frac{m-1}{m}*dp[1]+1dp[n?1]=m1??dp[n]+mm?1??dp[1]+1

dp[n?2]=1m?dp[n?1]+m?1m?dp[1]+1dp[n-2]=\frac{1}{m}*dp[n-1]+\frac{m-1}{m}*dp[1]+1dp[n?2]=m1??dp[n?1]+mm?1??dp[1]+1

dp[i]=1m?dp[i+1]+m?1m?dp[1]+1dp[i]=\frac{1}{m}*dp[i+1]+\frac{m-1}{m}*dp[1]+1dp[i]=m1??dp[i+1]+mm?1??dp[1]+1

那么dp[i]?dp[i?1]=1m(dp[i+1]?dp[i])dp[i]-dp[i-1]=\frac{1}{m}(dp[i+1]-dp[i])dp[i]?dp[i?1]=m1?(dp[i+1]?dp[i])

那么如果令di=dp[i]?dp[i?1]d_i=dp[i]-dp[i-1]di?=dp[i]?dp[i?1],不就是公比为mmm的等比数列吗?

dn=dp[1]?dp[0]=?1d_n=dp[1]-dp[0]=-1dn?=dp[1]?dp[0]=?1

∑i=1ndi=?dp[0]\sum\limits_{i=1}^{n}d_i=-dp[0]i=1n?di?=?dp[0](错位相减法)

所以可以等比数列求和快速解得



第二问,求连续n个数不相同的概率

定义dp[i]dp[i]dp[i]为已经iii个不相同,到达目标的期望

dp[i]=m?im?dp[i+1]+1m∑j=1idp[j]dp[i]=\frac{m-i}{m}*dp[i+1]+\frac{1}{m}\sum\limits_{j=1}^{i}dp[j]dp[i]=mm?i??dp[i+1]+m1?j=1i?dp[j]

dp[i+1]=m?i?1m?dp[i+2]+1m∑j=1i+1dp[j]dp[i+1]=\frac{m-i-1}{m}*dp[i+2]+\frac{1}{m}\sum\limits_{j=1}^{i+1}dp[j]dp[i+1]=mm?i?1??dp[i+2]+m1?j=1i+1?dp[j]

dp[i]?dp[i+1]dp[i]-dp[i+1]dp[i]?dp[i+1]得到

dp[i]?dp[i+1]=m?im?dp[i+1]?m?i+1m?dp[i+2]?1m?dp[i+1]dp[i]-dp[i+1]=\frac{m-i}{m}*dp[i+1]-\frac{m-i+1}{m}*dp[i+2]-\frac{1}{m}*dp[i+1]dp[i]?dp[i+1]=mm?i??dp[i+1]?mm?i+1??dp[i+2]?m1??dp[i+1]

dp[i]?dp[i+1]=m?i?1m(dp[i+1]?dp[i+2])dp[i]-dp[i+1]=\frac{m-i-1}{m}(dp[i+1]-dp[i+2])dp[i]?dp[i+1]=mm?i?1?(dp[i+1]?dp[i+2])

dp[0]?dp[1]=1dp[0]-dp[1]=1dp[0]?dp[1]=1

dp[1]?dp[2]=mm?1dp[1]-dp[2]=\frac{m}{m-1}dp[1]?dp[2]=m?1m?

dp[2]?dp[3]=mm?1?mm?2dp[2]-dp[3]=\frac{m}{m-1}*\frac{m}{m-2}dp[2]?dp[3]=m?1m??m?2m?

把上面所有等式相加得到

dp[0]?dp[n]=1+mm?1+mm?1?mm?2....dp[0]-dp[n]=1+\frac{m}{m-1}+\frac{m}{m-1}*\frac{m}{m-2}....dp[0]?dp[n]=1+m?1m?+m?1m??m?2m?....

#include <bits/stdc++.h>
using namespace std;
int t;
int quick_pow(int x,int n)
{int ans=1;while( n ){if( n&1 )	ans=ans*x;n>>=1;x=x*x;}	return ans;
}
int main()
{while( cin >> t ){while( t-- ){int ok,m,n;cin >> ok >> m >> n;if( ok ){double ans=1,temp=1;for(int i=1;i<=n-1;i++){temp*=m*1.0/(m-i);ans+=temp;}printf("%.6lf\n",ans);}else{double ans=(1.0-quick_pow(m,n))/(1.0-m);printf("%.6lf\n",ans);}}}
}