hdu 3750 Guess Game 数学期望

博客分享了在HDU 3750 Guess Game问题中,如何处理数学期望计算时的精度问题。作者在比赛中遇到递归计算错误,后来学到一个技巧:先将数值放大避免精度丢失,然后进行四舍五入,再缩小回原规模,从而正确得出保留小数位的答案。这个方法对于处理精度敏感的计算问题十分有用。
摘要由CSDN通过智能技术生成
 

 

hdoj 3750

http://acm.hdu.edu.cn/showproblem.php?pid=3750

 

 

Guess Game

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 254    Accepted Submission(s): 143


Problem Description
Bob plays the "guess the number right" with Alice recently,the game's rule is that Alice give Bob a upper limit number N ,then he write any of a number on paper which Bob can't know what it is and the number must be between 1 and N.Bob has many chances to guess the number and every time when Bob guesses Alice will tell him if his is bigger than the correct number or small than the correct number until he is right.
Now the Bob wanted to use binary search method to guess the right number, because he knows this method is quite fast to find the right number.
 
Input
We test the problem in many cases.Each case begin with one integers N( 1<= N <= 100000 ).
 
Output
Output the expected number of chances required to guess the number right, which accurate to 2 fractional digits.
 
Sample Input
  
  
2 3  
Sample Output
  
  
1.50 1.67

 

菜鸟杯上的一道题

我当时直接按照期望的定义来做的 递归的代码
比赛的时候一直错
很无语 而且浪费了很多时间

现在终于法相当时错的原因了 有点想砍人的冲动……

不过因为这个我学到了一个技巧。

首先说明:
在做要求保留精度的题时 原则是能先整数运算尽量整数运算 最后再四舍五入保留小数。

下面是技巧
比如这题

经过我对此题深入的一番研究
发现:
当输入数据时40时
正确答案是4.57500000 保留2位小数是4.58
我的答案是4.57499999 保留2位小数是4.57

你说能不让人想砍人吗?

这题我是这样AC的
4.5749999先乘以100000-->457499.99再+0.5-->457500.49取整-->457500再除以100000-->4.57500保留2位小数输出-->4.58

这个技巧我觉得还是重要
以后遇到怀疑自己答案精度问题的题时(特别是中途四舍五入了很多次而答案又很像的题) 可以考虑这个技巧
先乘-->四舍五入-->再除回来-->四舍五入输出
当然具体乘多少看题目了
我这次乘的100000 也就是先多保留了5位小数 我试过*10但还是错

总之就是+一个很小的数

 

我的代码(递归中损失了不少精度 不过排名居然还更高):

#include<stdio.h>
#define eps 1e-6
double sum;
void expect(int now,int n,double s)
{
    int d=n/2;
    if(n==0) return;
    sum+=s*now/n;
    s=s*(1-1.0/n);
    if(n%2)
        expect(now+1,d,s);
    else
    {
        expect(now+1,d,s*d/(n-1));
        expect(now+1,d-1,s*(d-1)/(n-1));
    }
}
int main()
{
    int n,s;

    while(~scanf("%d",&n))
    {
        sum=0.0;
        expect(1,n,1.0);
        printf("%.2lf\n",sum+eps);
    }
    return 0;
}

 


其它的代码:(同学给我的 没看懂...)

#include<stdio.h>
int main() 
{ 
	int n,t,s,i,m; 
	while(~scanf("%d",&n)) 
	{ 
		t=1; 
		s=0; 
		m=n; 
		for(i=1;n>t;i++) 
		{ 
			s+=i*t; 
			n-=t; 
			t*=2; 
		} 
		s+=n*i; 
		printf("%d--->%.2lfn",n,(double)1.0*s/m); 
	} 
	return 0; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值