UVa11809 - Floating-Point Numbers

题目:

在这里插入图片描述

解题思路:

看到大家都用打表的方法AC这题的,我也就打了个表。因为M和E的范围都很小,最多也就300种情况,把每种情况的结果记录下来就行。根据计算机二进制的表示方式不难得知 ( 1 − 1 2 M − 1 ) ∗ 2 2 E − 1 = A ∗ 1 0 B (1-\frac{1}{2^{M-1}})*2^{2^E-1}=A*10^B (12M11)22E1=A10B由于E的值最大能达到30,也就是说 2 2 E − 1 2^{2^E-1} 22E1极大,直接算会超出限制,所以我们对等式两边同时取以10为底的对数,那么我们可以得到 l g ( 2 M − 1 − 1 ) − ( M − 1 ) ∗ l g 2 + ( 2 E − 1 ) ∗ l g 2 = l g A + B lg(2^{M-1}-1)-(M-1)*lg2+(2^E-1)*lg2=lgA+B lg(2M11)(M1)lg2+(2E1)lg2=lgA+B左边的值显然是定值,我们令它为t,那么接下来就是求A,B。由于0<A<10,那么0< l g A lgA lgA<1,则A就是小数部分,B就是整数部分,用两个数组分别记录A,B即可,此时打表完成。待会输入A,B直接提取即可。

接下来又有一个令人头疼的就是如何处理输入的问题,显然用三个变量分别存A,e,B是可以的,但是未免有点麻烦,判断0e0的时候又多出来一条语句(后来发现可以精简到很短的(雾)),然后我在一个大佬的博客里面看到了sscanf,然后我懵逼,这是啥,再看一下他的代码,woc,居然这么短,于是百度了一下就用上了,把代码剪短了很多。
这是那位大佬的blog:https://blog.csdn.net/ShannonNansen/article/details/42059693
然后只要在之前打好的表中遍历搜索比较就行了,double的精度导致小数部分的比较不可能多精准,于是我就比较到了0.00001。

下面是我的AC代码
#include <stdio.h>
#include <string.h>
#include <math.h>
long long E[12][32];
double M[12][32];
char s[103];
int main(void)
{
    double m,t;
    long  long e;
    for(int j=0; j<10; j++)
        for(int i=1; i<=30; i++)
        {
            m=1-pow(2,-1-j);e=pow(2,i)-1;
            t=log10(m)+e*log10(2);
            E[j][i]=t;M[j][i]=pow(10,t-E[j][i]);
        }
    while(scanf("%s",s),strcmp(s,"0e0"))
    {
        *(strchr(s,'e'))=' ';
        sscanf(s,"%lf %lld",&m,&e);
        for(int i=0; i<10; i++)
            for(int j=1; j<=30; j++)
                if(e==E[i][j]&&fabs(m-M[i][j])<0.00001)
                {printf("%d %d\n",i,j);break;}
    }
    return 0;
}

附:

我在vjudge上交了题后,本以为自己的代码已经够精简了,结果一看Leaderboard,雾草,居然那么多人直接用数学方法暴力求解,NB。代码也比我短一半,于是乎,来,上代码,嗷嗷嗷!!!

在这里插入图片描述
这个其实海星,我们只要数学功底好些其实都能写出来差不多的,唉,数学是硬伤。不过xls告诉我打比赛的时候还是打表速度快,直接用数学方法暴力求解代码虽然短但是没必要,而且耗时。于是我发现了下面这位老哥,这位老哥就NB了。
直接循环寻找,为了省时还用了位运算,而且他的输入处理,我真的是拜服,我感觉我的sscanf简直是弱爆了,不BB了,上图
在这里插入图片描述
总的来说这题还是有难度的,也是卡了我三四天,我还是比较辣鸡,给xls可能十几分钟就AC了吧。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值