期望的逆推 及 HDU 4652 Dice

版权声明:写得不好,转载请通知一声,还请注明出处,感激不尽 https://blog.csdn.net/As_A_Kid/article/details/82597353

Problem

HDU

Solution

鉴于Rayment的期望dp实在是太差了,他只好写一些套路的水题了……

什么叫期望的逆推呢。。?

那就是对于现在的状态S,我们去考虑它的所有后继状态 T 1 , T 2 T m ,且各个后继发生的概率是 p 1 , p 2 p m 和它们分别的转移代价 c 1 , c 2 c m ,那么就有 E ( S ) = i = 1 m ( E ( T i ) + c i ) p i

比如我们来看个简单的例子,问一个正常的硬币期望抛多少次可以得到正面?我们设这个答案为x,那么 x = 0.5 ( 0 + 1 ) + 0.5 ( x + 1 ) ,解方程可以得到 x = 1

那么我们来看这道题,其实是两个不同的问题。


对于第一个问题,我们设 f [ i ] 表示已经有i个连续相同的数字,离达到连续n个期望多少次。则有

f [ i ] = 1 m f [ i + 1 ] + m 1 m f [ 1 ] + 1

按照套路,作差可得 m ( f [ i + 1 ] f [ i ] ) = f [ i + 2 ] f [ i + 1 ]

然后我们又有 f [ 0 ] f [ 1 ] = 1 , f [ n ] = 0 ,上等比数列求和公式 a n s = f [ 0 ] = m n 1 m 1


对于第二个问题,设 f [ i ] 表示已经有i个连续不相同的数字,离达到连续n个期望多少次。

f [ i ] = m i m f [ i + 1 ] + j = 1 i f [ j ] m

我们又作差

f [ i ] f [ i + 1 ] = m i 1 m ( f [ i + 1 ] f [ i + 2 ] )

不会用求和公式了,直接暴力 O ( n ) 搞一搞就行了。

顺带一提,这个数据不知为什么用read会TLE,改成scanf就可以了。

Code

#include <cstdio>
#include <cmath>
#define rg register
using namespace std;
typedef long long ll;
template <typename Tp> inline int getmin(Tp &x,Tp y){return y<x?x=y,1:0;}
template <typename Tp> inline int getmax(Tp &x,Tp y){return y>x?x=y,1:0;}
template <typename Tp> inline void read(Tp &x)
{
    x=0;int f=0;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') f=1,ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    if(f) x=-x;
}
int z,m,n,op;
double ans,tmp;
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
    while(~scanf("%d",&z))
    {
        while(z--)
        {
            scanf("%d%d%d",&op,&m,&n);
            if(!op) ans=(pow(m,n)-1.0)/(m-1.0);
            else
            {
                tmp=1.0;ans=0.0;
                for(rg int i=0;i<n;i++) tmp*=1.0*m/(m-i),ans+=tmp;
            }
            printf("%.9lf\n",ans);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/As_A_Kid/article/details/82597353