ACM - ICPC World Finals 2013 B Hey, Better Bettor
原题下载:http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf
这题真心的麻烦……程序不长但是推导过程比较复杂,不太好想
题目翻译:
问题描述
“在赌场里,基本原则就是让他们玩下去以及让他们再来玩。他们玩得越久,他们会输的越多,最后,我们会得到一切”
(摘自1995年的电影Casino)
最近的经济衰退还没有影响到娱乐场所,包括赌场。赌场吸引广大玩家的竞争是很残酷的,有些赌场已经开始提供一些看上去很好的措施。有一个赌场正在提供以下的优惠:你可以在这个赌场里赌很多次。当你赌完之后,如果你的总资金减少了,这个赌场会把你损失的x%退还给你。显然,如果你赚了,你可以留下所有的钱。这个服务没有时间限制和金钱限制,但是你只能赎回一次。
为简单起见,假定所有的赌局会花费1块钱,如果你赢得了赌局,会返还2块钱。现在假设x等于20。如果你一共进行了10次赌局,且只赢得了其中3个,那么你一共会损失3.2块钱。如果你赢得了6次赌局,你会赢得2块钱。
给定x和赢得赌局的概率p%,写一个程序,计算在最优策略下你的最大期望收益。
输入格式
每个输入文件只包含一组测试数据。每个测试数据包含两个数字,第一个数字x(0≤x<100)表示返还比例,第二个数字p(0≤p<50)表示获胜概率。x和p最多只包含两位小数
输出格式
对每个测试数据输出一行,表示最大期望获利,当你的答案与标准输出的误差在0.001以内时,被认为是对的
样例输入
0 49.9
样例输出
0.0
样例输入
50 49.85
样例输出
7.10178453
数据规模和约定
0≤x<100,0≤p<50,x和p最多只包含两位小数
题目大意:
你去进行赌博,有p%的胜率,每赌一场花费1元,赢了会得到2元,输了就输了(^_^),你可以无限制赌下去,你可以选择在适当的时候使用一次返款机会,即如果你当前输着钱,赌场会返还给你你输钱的x%,但是只能返还一次,求最后可以赚到钱的期望值
思路分析:
这道题是典型的求数学期望的题,考虑到返款只能用一次,所以我们一定是在结束的时候使用这次机会。由于我们可以进行无限局赌博,所以我们的期望值与当前赌的局数无关,而是与当前赚了多少钱有关。我们定义\( f_i \)表示当前赚的钱数为\( i \)时所得收益的数学期望。此时我们就有了赌或不赌这两种决策方式,如果选择不赌且当前盈利为负(\( i < 0\))时,会得到\(|i|x\%\)的返款,我们可以得到关系式
\[f_i=max\left\{\begin{array}{ll}i&\mbox{i>0 且选择不赌}\\\left(1-x\%\right)i&\mbox{i<0 且选择不赌}\\p\%f_{i+1}+\left(1-p\%\right)f_{i-1}&\mbox{选择继续赌下去}\end{array}\right.\]
我们先在坐标系上把选择不赌的曲线画出来,会得到一条折点在原点的折线。假设现在坐标系中我们已经得到了当前的最优解,将它逐步调整成实际的最优解,回句话说,对于所有满足\(p\%f_{i+1}+\left(1-p\%\right)f_{i-1}>f_i\)的点全部用\(p\%f_{i+1}+\left(1-p\%\right)f_{i-1}\)来更新直至全部无法更新,由于\(p\%<50\%\),而且我们的折线的两支都是单增的,所以当i-1、i、i+1三个点位于一条直线上时我们始终不会更新i(以为不可能更优),所以我们只可能从原点开始进行更新,而且我们不可能无限制地更新(想想也知道,如果都输干净了还不如不再赌下去,赢得多了也应该见好就收),因为这个递推函数的增长率是渐进为线性的,也就是说会存在上下界两个点使得无法继续更新。至此我们已经找到了问题的突破口——不停地对当前序列进行更新直至无法更新,\(f_0\)即为所求
但是尽管如此,我们可能更新的上下界依然可能非常大,这样直接更新非常容易超时。换一种思路,如果我们已知上下界的话,我们可以通过求通项来计算出\(f_0\)的值
对于上下界内的这部分我们都满足\[p\%f_i=f_{i-1}+\left(1-p\%\right)f_{i-2},\]然后我们就得到了一个二阶线性递推数列,特征方程为\[x^2=\frac{1}{p\%}x+\frac{1-p\%}{p\%},\]因式分解之后解得\[x_1=1,\qquad x_2=\frac{1-p\%}{p\%},\]然后得到通项公式\[f_n=\left(\frac{1-p\%}{p\%}\right)^n\alpha+\beta,\]则\(f_0=\alpha+\beta\)即为所求,由于已知上下界i和j(i < j),上下界正巧和不赌的两种情况相等,因此我们可以得到两个方程\[\left\{\begin{array}{l}\left(1-x\%\right)i=\left(\frac{1-p\%}{p\%}\right)^i\alpha+\beta\\j=\left(\frac{1-p\%}{p\%}\right)^j\alpha+\beta\end{array}\right.,\]
为了简单起见,我们设\(k_w=\left(\frac{1-p\%}{p\%}\right)^w\),然后解得\[\alpha=\frac{\left(1-x\%\right)i-j}{k_i-k_j},\\\beta=j-k_j\alpha,\]
但是枚举上下界依旧会超时,我们通过对小数据暴搜发现当下界已定的时候\(f_0\)是关于上界的一个单峰的上凸函数,同样地下界已定时\(f_0\)是关于上界的单峰凸函数(这一点暂时不会证明……只是观察发现的,但事实上它真的成立,希望会证明的朋友不吝赐教),然后就可以用三分法求单峰函数极值(先三分下界,里面套着三分上界),最后可以得到答案。对三分法不熟悉的同学可以参照这个博客http://chenjianneng3.blog.163.com/blog/#m=0
算法流程:
三分下界 里面套着三分上界,计算出对应的\(\alpha+\beta\),(注意应用快速幂),求出极值
参考代码:
//date 20140126
#include <cstdio>
#include <cstring>
const int inf = ;
const double EPS = 1e-;
int l, r, m1, m2;
double x, p, q, ans;
void frenew(double &x, double y){if(y - x > EPS)x = y;}
inline double pow(double n, int x)
{
double ans = 1.0;
while(x)
{
if(x & )ans *= n;
n *= n;
x >>= ;
}
return ans;
}
inline double calc(int i, int j)
{
double sig = i * (x - 1.0) + j;
int n = j - i;
double a1 = sig * (q - 1.0) / (pow(q, n) - 1.0);
if(a1 < EPS)return 0.0;
double sig2 = a1 * (pow(q, -i) - 1.0) / (q - 1.0);
double res = sig2 + i * ( - x);
return res > EPS ? res : 0.0;
}
inline double work2(int w)
{
int l = , r = inf, v1, v2;
while(l + < r)
{
v1 = (l + l + r) / ;
v2 = (l + r + r) / ;
if(calc(w, v1) - calc(w, v2) < -EPS)l = v1; else r = v2;
}
double res = calc(w, l);
frenew(res, calc(w, l + ));
frenew(res, calc(w, r));
return res;
}
inline double solve()
{
int l = -inf, r = , v1, v2;
while(l + < r)
{
v1 = (l + l + r) / ;
v2 = (l + r + r) / ;
if(work2(v1) - work2(v2) < EPS)l = v1; else r = v2;
}
ans = work2(l);
frenew(ans, work2(l + ));
frenew(ans, work2(r));
return ans;
}
int main()
{
// freopen("bettor.in", "r", stdin);
// freopen("bettor.out", "w", stdout); while(scanf("%lf%lf", &x, &p) != EOF)
{
x /= 100.0; p /= 100.0;
q = (1.0 - p) / p;
printf("%.9lf\n", solve());
}
return ;
}
需要注意的细节:
1.注意浮点运算的误差和比较
2.对无穷大值不可以直接求幂,,需要进行特判
3.由于函数定义域是整数集,所以要注意三分的结束条件
ACM - ICPC World Finals 2013 B Hey, Better Bettor的更多相关文章
- ACM - ICPC World Finals 2013 C Surely You Congest
原题下载:http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf 题目翻译: 试题来源 ACM/ICPC World Fin ...
- ACM - ICPC World Finals 2013 A Self-Assembly
原题下载 : http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf 这道题其实是2013年我AC的第一道题,非常的开心,这 ...
- ACM - ICPC World Finals 2013 F Low Power
原题下载:http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf 题目翻译: 问题描述 有n个机器,每个机器有2个芯片,每个 ...
- ACM - ICPC World Finals 2013 I Pirate Chest
原题下载:http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf 题目翻译: 问题描述 海盗Dick受够了在公海上厮杀.抢劫 ...
- ACM - ICPC World Finals 2013 H Матрёшка
原题下载:http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf 题目翻译: 问题描述 俄罗斯套娃是一些从外到里大小递减的传 ...
- ACM - ICPC World Finals 2013 D Factors
原题下载:http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf 题目翻译: 问题描述 一个最基本的算数法则就是大于1的整数 ...
- [算法竞赛入门经典]Message Decoding,ACM/ICPC World Finals 1991,UVa213
Description Some message encoding schemes require that an encoded message be sent in two parts. The ...
- UVa210 Concurrency Simulator (ACM/ICPC World Finals 1991) 双端队列
Programs executed concurrently on a uniprocessor system appear to be executed at the same time, but ...
- 谜题 (Puzzle,ACM/ICPC World Finals 1993,UVa227)
题目描述:算法竞赛入门经典习题3-5 题目思路:模拟题 #include <stdio.h> #include <string.h> #define maxn 55 char ...
随机推荐
- Ubuntu 查看文件以及磁盘空间大小命令df
(1)查看文件大小 查看当前文件夹下所有文件大小(包括子文件夹) du -sh # du -h 15M ./package 16K ./.fontconfig 4.0K ...
- Mysql创建和删除用户
问题描述: Mysql中创建用户和删除用户 问题解决: (1)查询Mysql当前登录账户 (2)创建用户 方法一: 创建用户赋予用户所有权限: 新创建的用户可以在 ...
- float2int
flaot转int时,会直接舍弃小数为,但是当把f所在的地址的数据当成int解析时,就是另外的情况了. #include<iostream> using namespace std; in ...
- 【Asp.net MVC ---杂七杂八】
@RenderSection 母模板:_mainLayout.cshtml <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitio ...
- 【锋利的JQuery-学习笔记】遮罩层
效果图: 鼠标移动到上面后---> html: <div id="jnBrandList"> <ul> <li> <a href= ...
- uva 11489
简单博弈 #include <cstdio> #include <cstdlib> #include <cmath> #include <map> #i ...
- 11个实用jQuery日历插件
1. FullCalendar FullCalendar是很出名的jQuery日历插件,它支持拖拽等功能,整合了Google Calendar,而且可以通过JSON来绑定事件,设计师可以轻松地自定义日 ...
- Unity3dBug - OnEnable
最近 项目 因为 使用 active 代替 instantiate机制,很多时候 OnEnable 代理 OnStart. 然后发现一个 奇怪的 问题 void Awake() { Debug.Log ...
- 解决ORA-00020错误
解决ORA-00020错误 分类: Oracle2009-05-13 17:26 3398人阅读 评论(0) 收藏 举报 数据库sessionoraclesql服务器object 项目上使用的Orac ...
- hdu 3336 Count the string(思维可水过,KMP)
题目 以下不是KMP算法—— 以下是kiki告诉我的方法,好厉害的思维—— 就是巧用标记,先标记第一个出现的所有位置,然后一遍遍从标记的位置往下找. #include<stdio.h> # ...