t组询问,有一个有n个面的色子,现在有两种询问
- 询问最后m次抛色子的实验结果互相相同的抛色子的期望次数。
- 询问最后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;
}