YJC最近在研究世界杯,他拿一半财产压了德国队,另一半财产压了阿根廷队,结果可想而知。YJC表示非常angry,于是又开始研究博彩公司的盈利原理。
假设在世界杯决赛前,有n个人参与了赌博。第i个人认为法国队赢的概率是p[i],克罗地亚队赢的概率是1−p[i]。
对于每一只球队,如果根据博彩公司给出的赔率第i个人的期望收益非负,则他会给这只球队下注a[i]元
(设赔率为x,某人下注了y元,如果他赢了可以返还x∗y元,他输了则会返还0元。不论输赢,下注的钱均不返还)。
如果两只球队期望收益均非负,则他会给两只球队各下注a[i]元。
现在博彩公司要决定法国队和克罗地亚队的赔率,使得在自身收益最小的胜负情况下的收益最大。
输入格式
第一行输入一个数n,表示总人数。
接下来n行,每行两个实数a[i]和p[i],均保留不超6位小数。
输出格式
一个实数,表示无论比赛结果如何,博彩公司最小收益的最大值,保留6位小数。
样例1
样例输入
3
1 0.1
2.233 0.1
3.666 0.1
样例输出
0.000000
样例2
见下载文件
限制
对于10%的数据,保证n≤80。
对于30%的数据,保证n≤400。
对于50%的数据,保证n≤5000。
对于80%的数据,保证n≤100000。
对于100%的数据,保证n≤1000000,0≤a[i]≤100,0≤p[i]≤1。
时间限制:2s
内存限制:512MB
若法国队赔率为x,下注y
期望收益:x * y * p[i] + 0 * (1 - p[i]) - y = y * (x * p[i] -1)
y>0,则若x * p[i] >= 1就会下注
移项得图片中的结论 ,克罗地亚同理
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int N=1e6+15; int n; int id[N]; double ans; double a[N],p[N],sum[N]; bool cmp(int a,int b) {return p[a]>p[b];} int main() { scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%lf%lf",&a[i],&p[i]),id[i]=i; sort(id+1,id+1+n,cmp); for (int i=1;i<=n;i++) sum[id[i]]=sum[id[i-1]]+a[id[i]]; int l=1,r=n; while (l<=n&&r>=1) { double x1=1.0/p[id[l]],x2=1.0/(1-p[id[r]]); double s1=sum[id[l]],s2=sum[id[n]]-sum[id[r-1]]; ans=max(ans,min(s1+s2-s1*x1,s1+s2-s2*x2)); if (s1*x1>s2*x2) r--; else l++; } printf("%lf",ans); return 0; }