SHOI2002 百事世界杯之旅
题目链接:戳我
看到期望,想着不要从前转移。
一次后能买到不同种类的概率为\(\frac{n-i}{n}\)
两次后能买到不同种类的概率为\(\frac{i}{n}\times \frac{n-i}{n}\)
n次后能买到不同种类的概率为\((\frac{i}{n})^n\times \frac{n-i}{n}\)
设总期望为\(E=\frac{n-i}{n}\times1+\frac{i}{n}\times \frac{n-i}{n}\times 2+(\frac{i}{n})^2\times \frac{n-i}{n}\times 3+...+(\frac{i}{n})^{\infty}\times \frac{n-i}{n}\times{\infty}\)
\(\frac{i}{n}E=\frac{i}{n}\times \frac{n-i}{n}\times 1+(\frac{i}{n})^2\times \frac{n-i}{n}\times 2+...+(\frac{i}{n})^{\infty}\times \frac{n-i}{n}\times {\infty}\)
\(E=(\frac{i}{n})^0+(\frac{i}{n})^1+(\frac{i}{n})^2+....(1)\)
\(\frac{i}{n}E=(\frac{i}{n})^1+(\frac{i}{n})^2+....(2)\)
\((1)-(2)\;\; E=\frac{n}{n-i}\)
我们考虑\(f[i]\)表示已经买到了i个名字的期望次数
\(f[i+1]=f[i]+\frac{n}{n-i}\)
然后就可以递推了。
输出比较神奇,但是注意一点也不会出错的。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
#define MAXN 40
#define ll long long
using namespace std;
int n;
long long fv[MAXN],fn[MAXN];
inline ll gcd(ll x,ll y)
{
if(!y) return x;
else return gcd(y,x%y);
}
inline int solve(ll x)
{
int cur_ans=0;
while(x)
{
cur_ans++;
x/=10;
}
return cur_ans;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
scanf("%d",&n);
fv[1]=1,fn[1]=1;
for(int i=1;i<n;i++)
{
fv[i+1]=fv[i]*(n-i)+fn[i]*n;
fn[i+1]=fn[i]*(n-i);
long long cur=gcd(fn[i+1],fv[i+1]);
fn[i+1]/=cur,fv[i+1]/=cur;
}
ll cur=fv[n]/fn[n];
if(fv[n]%fn[n]==0) cout<<cur<<endl;
else
{
fv[n]-=cur*fn[n];
int len1=solve(cur);
for(int i=1;i<=len1;i++) printf(" ");
printf("%lld\n",fv[n]);
int len2=solve(max(fv[n],fn[n]));
printf("%lld",cur);
for(int i=1;i<=len2;i++) printf("-"); puts("");
for(int i=1;i<=len1;i++) printf(" ");
printf("%lld\n",fn[n]);
}
return 0;
}