Uva 557 – Burger (log(x)应用 , 组合数学)
来源:互联网 发布:jdk1.7 windows 64 编辑:程序博客网 时间:2024/05/21 15:06
传送门: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=115&page=show_problem&problem=498
题意:Ben Bill生日,邀请朋友去m记。有2n个人(包括Ben Bill)。n个汉堡包和n个乳酪汉堡。从Bill左边的女孩开始分汉堡,一直往左,最后转一圈回到Ben 和 Bill 。分汉堡的方法是用一枚硬币,每个人扔出正面就拿汉堡,反面就拿另一种。求出Ben 和Bill 能拿到同一种汉堡的概率。n<=10W
思路:
只要两种汉堡都剩下至少一个,能拿到其中一种的概率都是0.5。本题可以先求二人刚好分得不同的汉堡(就是前2n-2个人有n-1个拿到一种汉堡,另外n-1个拿到另外一种)的概率,在用1减去。
p = 1 – C (2n-2 , n-1) * 0.5 2n-2 (2n-2重伯努利实验满足二项分布。)
不过2n可以高达10W,对于组合排列数C来说。10W的结果数量级大概是10W ! 的一半。十分庞大,double根本装不下。即使可以使用高精度浮点模板,如此高的精度也使得时间复杂度十分大。而0.5的10W次方又是一个相当小的数字,精度过高。如果用double储存会直接被当做无穷小也就是零了。不过如果二者做乘积,结果数量级抵消。所以现在面临的问题是中间结果太大。
这种情况通常可以通过分步运算,保持数据在可控的范围内。 C (2n-2 , n-1) = (2n-2)! / ( (n-1) ! *( n-1) ! )这样可以分步,先乘分子的一部分,再除分母的一部分。结果可以保证准确。不过很遗憾,10W次不断的浮点乘除,巨大的时间复杂度还是不能通过数据。
利用log函数可以将数据的数量级大大减少。10的10W次方经过log函数处理,结果也就是10W左右。
结果可以这样写
p = 1 – 10 a
a= log10 C (2n-2 , n-1) +(2n-2) * log10 0.5
= log10(2n-2) ! -log10 (n-1)! -log10(n-1) ! ) + (2n-2) * log10 0.5.
可以预先求出1~10W 阶乘对10取对数的结果,这样在程序中可以直接调用!代入能直接得出结果。加上一开始预处理求1~10W 阶乘对10取对数的结果。这是相当大的一个优化了。
#include<iostream>#include<cstdio>#include<limits.h>#include<cmath>#include<cstdlib>#include<cstring>using namespace std;double log_n[100000];const double aa = log(0.5);int main(){ int i,j,t; double ans ; log_n[0] = 0; for(i=1;i<=100000;i++){ // 可以利用之前的结果递推a[i] = log(i!) = log((i-1)!*i) = a[i-1] + log(i); log_n[i] = log_n[i-1] + log(i) ; } scanf("%d",&t); while(t--){ scanf("%d",&i); j = i/2; ans = log_n[i-2] - log_n[j-1] - log_n[j-1]; ans += (i - 2) * aa; ans = exp(ans); printf("%.4lf\n",1-ans); } return 0;}
- Uva 557 – Burger (log(x)应用 , 组合数学)
- UVA 557 Burger (数学)
- uva 557 - Burger
- UVa 557 - Burger
- uva 557 Burger
- UVa 557 - Burger
- UVa 557 - Burger (概率)
- UVa 557 - Burger
- UVA - 557 Burger
- UVA 557(p344)----Burger
- uva 557 Burger
- uva 557 - Burger(概率)
- UVA - 557 Burger 排列组合 概率
- Burger - UVa 557 概率dp
- UVA 557 - Burger(概率 递推)
- 习题10-12 UVA - 557 Burger 汉堡
- uva 11538 组合数学
- UVA 19889 组合数学
- 指针的实质以及指针的强制转换
- mongodb 学习
- USB枚举过程
- 排序之归并操作
- 软件工程—软件计划
- Uva 557 – Burger (log(x)应用 , 组合数学)
- java.io 序列化 总结(一)---Serializable 和 Externalizable 的区别与联系
- javascript常用语句大全
- WINPCAP编程环境设置
- Linux动态库与静态库
- android绚丽的ListView表格效果的实现
- lua 排序
- 让ie6也支持websocket
- ZOJ 1788 Quad Trees (朴素BFS)