Dice

Dice

t组询问,有一个有n个面的色子,现在有两种询问

  1. 询问最后m次抛色子的实验结果互相相同的抛色子的期望次数。
  2. 询问最后m次抛色子的实验结果互不不同的抛色子的期望次数。

(1≤m,n≤10^6)

注意到样本空间无限大,于是考虑无后效性递推做法,设(E(n))表示满足对应询问的抛色子的期望数。

询问1:

不难有

[E(0)=E(1)+1 ]

[E(1)=E(2)frac{1}{n}+E(1)frac{n-1}{n}+1 ]

[E(2)=E(3)frac{1}{n}+E(1)frac{n-1}{n}+1 ]

[... ]

[E(m-1)=E(m)frac{1}{n}+E(1)frac{n-1}{n}+1 ]

[E(m)=0 ]

注意到类似数列形式,想办法用数列的等差数列法推通项公式,于是有

[E(i)=E(i+1)frac{1}{n}+E(1)frac{n-1}{n}+1 ]

[E(i+1)=E(i+2)frac{1}{n}+E(1)frac{n-1}{n}+1 ]

两式相减,我们有

[E(i+1)-E(i)=frac{1}{n}(E(i+2)-E(i+1)) ]

[E(i+2)-E(i+1)=n imes[E(i+1)-E(i)] ]

对右式无限递归,而我们又有(E(1)-E(0)=-1),所以

[E(i+1)-E(i+2)=n^{i+1} ]

所以,我们有

[E(0)-E(1)=1 ]

[E(1)-E(2)=n ]

[E(2)-E(3)=n^2 ]

[E(3)-E(4)=n^3 ]

[... ]

[E(m-1)-E(m)=n^{m-1} ]

累加我们有

[E(0)=1+n+...+n^{m-1}=frac{n^m-1}{n-1} ]

以此跑快速幂即可。

询问2:

同样不难推出

[E(0)=E(1)+1 ]

[E(1)=E(2)frac{n-1}{n}+E(1)frac{1}{n}+1 ]

[E(2)=E(3)frac{n-2}{n}+[E(1)+E(2)]frac{1}{n}+1 ]

[... ]

[E(m-1)=E(m)frac{n-m+1}{n}+[E(1)+E(2)+...E(m-1)]frac{1}{n}+1 ]

同样考虑等差,于是我们设出

[E(i)=E(i+1)frac{n-i}{n}+[E(1)+...+E(i)]frac{1}{n}+1 ]

[E(i+1)=E(i+2)frac{n-i-1}{n}+[E(1)+...+E(i+1)]frac{1}{n}+1 ]

相减我们有

[E(i+1)-E(i)=E(i+2)frac{n-i-1}{n}-E(i+1)frac{n-i}{n}+E(i+1)frac{1}{n} ]

[E(i+1)-E(i)=E(i+2)frac{n-i-1}{n}-E(i+1)frac{n-i-1}{n} ]

[E(i+1)-E(i)=[E(i+2)-E(i+1)]frac{n-i-1}{n} ]

[E(i+2)-E(i+1)=frac{n}{n-i-1}[E(i+1)-E(i)] ]

同样无限递归我们有

[E(i+2)-E(i+1)=-frac{n^{i+1}}{(n-i-1)(n-i)...(n-1)} ]

于是我们有

[E(0)-E(1)=1 ]

[E(1)-E(2)=frac{n}{n-1} ]

[E(2)-E(3)=frac{n^2}{(n-1)(n-2)} ]

[... ]

[E(m-1)-E(m)=frac{n^{m-1}}{(n-1)(n-2)...(n-m+1)} ]

累加我们即可以得到(E(0))的值,以此(O(n))累加即可。

参考代码:

#include <iostream>
#include <cstdio>
#define il inline
#define ri register
using namespace std;
il void fpen(double,int),pen(int);
il double pow(double,int),ask1(double,double),
    ask2(double,double);
int main(){
    int lsy,c,n,m;
    while(scanf("%d",&lsy)!=EOF){
        while(lsy--){
            scanf("%d%d%d",&c,&n,&m);
            if(!c)fpen(ask1(n,m),9);
            else fpen(ask2(n,m),9);putchar('
');
        }
    }
    return 0;
}
il void pen(int x){
    if(x>9)pen(x/10);putchar(x%10+48);
}
il void fpen(double x,int n){
    pen(x),x-=(int)x,putchar('.');
    while(n--)
        x*=10,putchar((int)x+48),x-=(int)x;
}
il double ask1(double n,double m){
    return (pow(n,m)-1)/(n-1);
}
il double ask2(double n,double m){
    double ans(1),opt(1);int i;
    for(i=1;i<m;++i)
        opt=opt*n/(n-i),ans+=opt;
    return ans;
}
il double pow(double x,int y){
    double ans(1);while(y){
        if(y&1)ans*=x;
        x*=x,y>>=1;
    }return ans;
}
原文地址:https://www.cnblogs.com/a1b3c7d9/p/10839526.html