• 省赛前最后一次总结


    经过这一个月的做题训练,思维能力,跟做题感觉,都有所有能力也有所提高。没有太多感想,就是继续努力。
    问题:
    1.埃氏筛法

    int a[maxx];
    int b[maxx+1];
    int gg(int n)
    {
        int p=0;//记录素数个数
        for(int i=0;i<n+1;i++)b[i]=1;
        b[0]=0;
        b[1]=0;
        //准备完毕
        for(int i=2;i<=n;i++){
            if(b[i]){
                a[p++]=i;//记录素数和个数
                for(int j=2*i;j<=n;j+=i)b[j]=0;//剔除倍数
            }
        }
        return p;//返回素数个数
    }
    

    2.精度计算

    一、基础篇

    1、一般浮点数使用double,范围为大概为-10^308 ~ 10^308,有效精度为15~16位10进制数。

    2、一般没事(比如内存问题)不用float,而使用double,一个double占8个字节。

    3、信息学竞赛一般使用scanf和printf输入输出,而浮点数的输入是scanf("%lf",
    &x),浮点数的输出是printf("%f", x),注意两个是不一样的。使用printf("%lf",
    x)来输出浮点数有可能会出错,因为标准中规定double输出是使用"%f"的,并非所有编译器都实现了"%lf"的输出(比如POJ的G++就没有)。

    4、在实在没有办法的情况下可以使用long double,但标准只规定了其精度一定不小于double,有可能等于double请注意。

    5、double的精度有限,并不是精确的存储数字,而且它是二进制存储,如下图,0.1 *
    10不等于1,因为0.1在计算机中不是我们认为的1/10,下图有0.1在double下的值,可以看出并不完全等于0.1。

    6、为了解决上面不能直接比较的问题,我们可以设置一个精度EPS,来辅助我们检验两个数是否非常接近。EPS的设置要看题目具体情况,一般情况下可以设成1e-8。

    定义函数:

    inline int sgn(double x) {
        if(fabs(x) < EPS) return 0;
        return x > 0 ? 1 : -1;
    }
    

    用上述函数来判断一个数是否大于小于或等于0。

    x = 0 写成 sgn(x) == 0

    x < 0 写成 sgn(x) < 0

    x > 0 写成 sgn(x) > 0

    x > y 写成 sgn(x - y) > 0

    x == y 写成 sgn(x - y) == 0

    x >= y 写成 sgn(x - y) >= 0

    以此类推。

    7、上述函数的一种常数优化的写法:

    inline int sgn(double x) {
        return (x > EPS) - (x < -EPS);
    }
    

    二、进阶篇(陷阱篇)

    1、在竞赛中,可能存在给一个double多次计算后,非常接近0的情况,但是,它可能是-0.000000000000000001(一下子举不出实际的例子……),这时输出会变成-0.00,在一部分精确比较的题目上可能会出错,解决方案为输出的时候加上一个EPS(当然不能排除出题人自己煞笔的情况……),即printf("%f",
    ans + EPS)。

    2、如果一个double,要把一个数组里的浮点数累加起来(即 double sum = accumlate(arr.begin(),
    arr.end(),
    0)),如果数组里的数相差可能会比较大,应该从小到大累加。否则可能会发生加了一个很大的浮点数之后,再加一个很小的浮点数,因为精度的原因,跟没加一样(比如一个极端的例子,1e100

    • 1e-100还是等于1e100)。因为比较小的数多了,还是会影响到答案的,并不是可以简简单单被忽略的。

    3、在计算一个数减去一组数的时候(即double sum = x - accumlate(arr.begin(), arr.end(),
    0)),应该先把数组里的数全加起来,再用那个数来减。否则跟上面一样,可能会出现减去了一个很小的数,跟没减一样。

    4、二分的时候,EPS设置不当,可能会出现奇怪的问题(特别是有多次二分而对着两次二分要求的精度不一样的时候),这时可以采取另一种写法:

    double binary_search(double l, double r) {
        for(int i = 0; i < 100; ++i) {
            double mid = (l + r) / 2;
            if(check(mid)) l = mid;
            else r = mid;
        }
        return l;
    }
    

    循环次数可按需设置,一般100都够,对时间要求高可以设小一点。

    5、在连乘的时候,浮点数可能会丢比较多的精度,此时可以利用公式x1 * x2 * …… * xn = exp(ln(x1 * x2 * ……

    • xn)) = exp(ln(x1) + ln(x2) + ……ln(xn)),取他们的对数相加,再求次幂。

    比如在计算阶乘的时候,可以:

    double Factorial(int n) {
        double res = 0;
        for(int i = 1; i <= n; ++i)
            res += log(i);
        return exp(res);
    }
    

    当然有必要的时候(其实是大多时候)我们可以先不exp()先返回,作完后续运算再exp()

    3.超时
    数组过大每次都要memset初始化,导致超时。
    有些时候,数组没必要memset,卡了我七次超时,一重循环。

    4.素数筛打表的时候默认为1为素数
    5. 昨晚微积分定积分公式忘记了,没做出来题。
    6. acos(-1.0)=Π;精度很高,比手打的define精度高不少,用3.14159265,精度都不够。

    放平心态,省赛加油。

  • 相关阅读:
    网页支付宝接口使用
    @Valid注解的使用springmvc pojo校验
    Git
    面试宝典
    Navicat 破解版(操作非常简单)
    JAVA中List,Map,Set接口的区别
    java 枚举示例
    springcloud和springboot是什么关系?
    java面试经常涉及到的
    asp.net 报错 SAP 报错 试图加载格式不正确的程序。 (异常来自 HRESULT:0x8007000B)
  • 原文地址:https://www.cnblogs.com/lunatic-talent/p/12798972.html
Copyright © 2020-2023  润新知