Luogu P4550 收集邮票
题目链接:Click here
Solution:
本题直接推价格似乎很难,考虑先从购买次数入手
设购买次数\(g(i)\)为当前有\(i\)种不同的邮票,要买到\(n\)种的期望购买次数
可以由期望的定义得到式子:\(g(x)=\sum_{i=0}^{+\infty}P(i,x)\),其中\(P(i,x)\)为买\(i\)次从\(x\)种买到\(n\)种的概率
对于一个局面,记它可以转移到的局面集合为\(to\),则它的期望可以表示为
其中\(P(v)\)表示从\(v\)局面转移到\(u\)局面的概率,\(cost(v,u)\)表示从\(v\)转移到\(u\)局面的的代价
那么对于本题也可以如此转化:\(g(x)=\frac{x}{n}(g(x)+1)+\frac{n-x}{n}(g(x+1)+1)\)
也很好理解,因为再抽一张卡,可能抽到已经抽到的,也可能抽到新的,而转移的代价都为1
显然,\(g(n)=0\),再把式子转化一下,就可以得到\(g(x)\)的计算方式:
然后我们再考虑设\(f(i,j)\)表示当前有\(i\)种邮票,下次购买要花\(j\)元时,买到\(n\)种的期望花费
我们知道购买要\(j\)元,结合题意,就能很好的推出\(f(i,j)\)的转化方程:
我们考虑一下\(f(i,j)\)的定义,便可以得出式子:
这里\(P\)的定义同上文\(g(x)\)定义式中的\(P\),然后我们再考虑表示\(f(i,j+1)\),很简单,带入即可
考虑表示将\(f(i,j+1)\)减去\(f(i,j)\)可得:\(f(i,j+1)-f(i,j)=\sum_{u=0}uP(u,i)\)
可以发现它与前面的期望定义式是一样的,则我们得到式子:\(f(i,j+1)=f(i,j)+g(i)\)
则我们可以把\(f(i,j)\)表示一下:
事实上我们只需求出\(f(0,1)\),而在递推中可以发现\(j\)是没有变化的,则可以直接忽略\(j\)
Code:
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+1;
int n;double u,f[N],g[N];
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
int main(){
n=read();f[n]=g[n]=0;u=n;
for(int i=n-1;~i;i--) g[i]=g[i+1]+u/(u-i);
for(int i=n-1;~i;i--){
double x=i,y=n-i;
f[i]=f[i+1]+g[i+1]+x/y*g[i]+u/y;
}Pintf("%.2lf",f[0]);
return 0;
}
题外话:推的时候发现了另外一个式子:设\(P(x)\)表示用\(x\)步刚好取到所有邮票的概率,则:
式子也很好理解,保证最后取到没取到的那种,再取完其它的种类,剩下的步数只要不取到最后那枚就行
则本题也可以这样求:
然后对这个式子求个通项就行了,不过我还不会求。。。