您的位置:首页 > 其它

【Luogu1291】百事世界杯之旅(动态规划,数学期望)

2018-02-07 16:46 302 查看

题面

洛谷

题解

设f[i]表示已经集齐了i个名字的期望

现在有两种方法:

先说我自己的:

f[i]=f[i−1]+1+(1−p)(1∗p1+2∗p2+....)

其中p=i−1n

为什么,很简单

首先要多收集一个,期望+1是显然的

但是还可能一直买到了已经有的名字中的一个

有p的概率多买一个

p2的概率多买两个

这样无穷的算下去

然后对于后面那个式子

做两次错位相减(其实就是一个无穷级数)

推出

f[i]=f[i−1]+1+i−1n−(i−1)

然后递推就行了

第二种方法:

fdf的方法(感觉这种方法也很强呀)

设f[i]表示已经收集了i个

收集到n个需要的期望

f[i]=in(f[i]+1)+n−in(f[i+1]+1)

n−inf[i]=n−inf[i+1]+1

f[i]=f[i+1]+nn−i

初值:f[n]=0

倒着算即可

贴上我自己的代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int n;
int ws(ll x)
{
int ret=0;
while(x)++ret,x/=10;
return ret;
}
struct Num
{
ll a,b;
void easy()
{
ll d=__gcd(a,b);
a/=d;b/=d;
}
void output()
{
easy();
if(b==1){printf("%lld\n",a);return;}
ll k=a/b;a-=k*b;
int blk=ws(k),ss=max(ws(a),ws(b));
for(int i=1;i<=blk;++i)putchar(' ');
printf("%lld\n",a);
printf("%lld",k);
for(int i=1;i<=ss;++i)putchar('-');putchar('\n');
for(int i=1;i<=blk;++i)putchar(' ');
printf("%lld\n",b);
}
}f[50];
Num operator+(Num a,Num b)
{
ll d=a.b/__gcd(a.b,b.b)*b.b;
return (Num){a.a*(d/a.b)+b.a*(d/b.b),d};
}
Num operator*(Num a,Num b)
{
Num c=(Num){a.a*b.a,a.b*b.b};
c.easy();
return c;
}
int main()
{
n=read();
f[0]=(Num){0,1};
for(int i=1;i<=n;++i)
{
f[i]=f[i-1]+(Num){1,1};
f[i]=f[i]+(Num){i-1,n-i+1};
}
f
.output();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: