D. Gambler‘s Ruin

D. Gambler’s Ruin

题目链接

题目大意

需要设置两个赔率x和y。使得求出一个最佳的赔率,使得赌博公司利润最大
使得 [ s x + s y − m a x ( s x ∗ x , s y ∗ y ) ] 最大 使得 [s_x + s_y - max(s_x *x,s_y *y)] 最大 使得[sx+symax(sxx,syy)]最大

题解思维

当某个(赌徒) p i 的赔率满足 p i ∗ x > = 1 时,也就是 x > = 1 p i 时 , 赌徒会下注 c i 当某个(赌徒)p_i 的赔率满足p_i *x >=1时,也就是x>=\frac{1}{p_i}时,赌徒会下注c_i 当某个(赌徒)pi的赔率满足pix>=1时,也就是x>=pi1,赌徒会下注ci

另一个则是 y 的,同理得到, y > = 1 1 − p i 时 , 赌徒会下注 c i 另一个则是y的,同理得到,y>=\frac{1}{1-p_i}时,赌徒会下注c_i 另一个则是y的,同理得到,y>=1pi1,赌徒会下注ci

由于 0 < = p i < = 1 ,所以当 p i 越来越小时, 1 p i 越来越大,所以我们需要对输入的数据根据 p i 进行排序【本文中使用了降序排序】 由于0<=p_i<=1,所以当pi越来越小时,\frac{1}{pi}越来越大,所以我们需要对输入的数据根据p_i 进行排序【本文中使用了降序排序】 由于0<=pi<=1,所以当pi越来越小时,pi1越来越大,所以我们需要对输入的数据根据pi进行排序【本文中使用了降序排序】

假设排序完成后的数组,中元素是以 a 0 , a 1 , ⋅ ⋅ ⋅ , a n ,这样的数组 假设排序完成后的数组,中元素是以a_0,a_1,···,a_n,这样的数组 假设排序完成后的数组,中元素是以a0,a1,⋅⋅⋅,an,这样的数组

如果有 p i 相同的元素,可以将它们合并 如果有p_i 相同的元素,可以将它们合并 如果有pi相同的元素,可以将它们合并

我们假设设置了 1 a 4 为赔率,那么在它【 a 4 】之前的元素,显然都满足下注的条件 我们假设设置了\frac{1}{a_4}为赔率,那么在它【a_4】之前的元素,显然都满足下注的条件 我们假设设置了a41为赔率,那么在它【a4】之前的元素,显然都满足下注的条件

由于 y 是 1 − p i 关联的,显然和 x 相反,也就是,当认定 1 1 − a j 时, a 之 后的都满足条件 由于y是1-p_i关联的,显然和x相反,也就是,当认定\frac{1}{1-aj}时,a_之后的都满足条件 由于y1pi关联的,显然和x相反,也就是,当认定1aj1时,a后的都满足条件

问题就简化成了,找到 a i , a j 使得,使得赌博公司利润最大 问题就简化成了,找到a_i,a_j使得,使得赌博公司利润最大 问题就简化成了,找到ai,aj使得,使得赌博公司利润最大

对于 s x ∗ x ,其实可以理解为,这个排序好后的前缀和和 ( 1 a i ) 的乘积 = v 1 = ( 1 a i ) ∗ ∑ i = 1 i c i 对于s_x *x,其实可以理解为,这个排序好后的前缀和和(\frac{1}{a_i})的乘积=v1 =(\frac{1}{a_i})*\sum_{i=1}^{i}{c_i} 对于sxx,其实可以理解为,这个排序好后的前缀和和(ai1)的乘积=v1=(ai1)i=1ici

对于 s y ∗ y ,其实可以理解为,这个排序好后的后缀和和 ( 1 1 − a j ) 的乘积 = v 2 = ( 1 1 − a j ) ∗ ∑ i = j n − j c i 对于s_y *y,其实可以理解为,这个排序好后的后缀和和(\frac{1}{1-a_j})的乘积=v2 =(\frac{1}{1-a_j})*\sum_{i=j}^{n-j}{c_i} 对于syy,其实可以理解为,这个排序好后的后缀和和(1aj1)的乘积=v2=(1aj1)i=jnjci

发现,当i,j越来越大时,v1是越来越大,v2越来越小
由于存在 m a x ( s x ∗ x , s y ∗ y ) , 那么显然,当固定 i 或 j 时,另外一个的变化会有一个零界点,当它越过零界点时, m a x 的值会产生变化 由于存在max(s_x *x,s_y *y),那么显然,当固定i或j时,另外一个的变化会有一个零界点,当它越过零界点时,max的值会产生变化 由于存在max(sxx,syy),那么显然,当固定ij时,另外一个的变化会有一个零界点,当它越过零界点时,max的值会产生变化

假设固定了某个 a i , 使得 S x ∗ x 固定,假设 p 从数组 a n 开始, a j 是从 a n 开始倒着的遍历 , 希望找到第一个 a j 使得它大于或等于 S x ∗ x 假设固定了某个a_i,使得Sx*x固定,假设p从数组a_n开始,a_j是从a_n开始倒着的遍历,希望找到第一个a_j使得它大于或等于Sx*x 假设固定了某个ai,使得Sxx固定,假设p从数组an开始,aj是从an开始倒着的遍历,希望找到第一个aj使得它大于或等于Sxx

假设这个 a j 的索引是 p , 那么当固定 a i ( s x ∗ x )时,所能求得的最大利润显然,在 p 时 [ 大的是 y ] ,或者 p + 1 时【大的是 x 】产生。 假设这个a_j 的索引是 p ,那么当固定a_i(s_x*x)时,所能求得的最大利润显然,在p时[大的是y],或者p+1时【大的是x】产生。 假设这个aj的索引是p,那么当固定aisxx)时,所能求得的最大利润显然,在p[大的是y],或者p+1时【大的是x】产生。

有了上面的思路之后,就可以进行程序的编写了了,程序如下

#include<bits/stdc++.h> 
using namespace std;

int n;
#define ll long long
const int lim  = 1e6+10;
const double eps = 1e-10;
 
pair<double, ll> a[lim];
ll pres[lim], sufs[lim];
int main()
{
	 ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
	cin>>n;	
	for(int i=1;i<=n;i++)
	{
		cin>>a[i].first>>a[i].second;
	}
	sort(a+1,a+n+1,greater<pair<double,ll>>());
	int cnt=0;
	for(int i=1;i<=n;i++)
	{
		if(i==1||fabs(a[i].first - a[i - 1].first) > eps)	
			a[++cnt] = a[i];
		else
			a[cnt].second += a[i].second;
	}
	n = cnt;
	for (int i = 1; i <= n; ++i) pres[i] = pres[i - 1] + a[i].second;
    for (int i = n; i; --i) sufs[i] = sufs[i + 1] + a[i].second;
    
    double ans = 0;
    //找到临界点,并将它和答案进行更新 
    for (int i = 1, p = n; i <= n; ++i) {
		if (i == n || fabs(a[i].first - a[i + 1].first) > eps) 
			while (p > i && pres[i] / a[i].first > sufs[p] / (1 - a[p].first)) --p;
	    ans = max(ans, pres[i] + sufs[p + 1] - pres[i] / a[i].first);
	    if (i >= p) break;
	    ans = max(ans, pres[i] + sufs[p] - sufs[p] / (1 - a[p].first));
    }
    cout << fixed << setprecision(10) << ans << '\n';
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值