zoukankan      html  css  js  c++  java
  • 简单的卡常数【OI缩水版】

    一、为什么要卡常数?

    这里写图片描述

    • OI中数据结构与常数优化关系很大的
    • 如果你常数好可以暴力过数据结构题啦~
    • 如果你常数不好即使复杂度一样也会被出题人卡~

    二、常用的卡常数方法

    1、卡IO(输入输出)

    比较简单的写法:

    int readint(){
        int op=1,x=0;  char ch=getchar();
        while(ch<'0' || ch>'9'){if(ch=='-')op=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return op*x;
    }
    void outint(int x){
        if(x<0){putchar('-');x=-x;}
        if(x>9)outint(x/10);
        putchar(x%10+'0');
    }

    比较奇怪的写法

    mmap

    2、卡编译

    2.1 C++内联函数inline

    由编译器在编译时会在主程序中把函数的内容直接展开替换,减少了内存访问。(如果是递归可能会展开前几层的运算吧?)

    int max(int a, int b){return a>b?a:b;}//原函数
    inline int max(int a, int b){return a>b?a:b;}//前面直接加inline就好了。
    2.2 CPU寄存器变量register

    对于一些频繁使用的变量,可以声明时加上该关键字,运行时可能会把该变量放到CPU寄存器中,只是可能,不保证有效。特别是你变量多的时候,一般还是丢到内存里面的。
    比较下面两段程序:

    register int a=0;
    for(register int i=1;i<=999999999;i++)a++;
    int a=0;
    for(int i=1;i<=999999999;i++)a++;

    优化:0.2826 second
    不优化:1.944 second


    3、卡计算

    3.1 取模优化
    占坑待填,据说 https://loj.ac/article/327
    3.2 加法优化

    ++i代替i++
    1. 后置++需要保存临时变量以返回之前的值,在 STL 中非常慢。
    2. 事实上,int的后置++ 在实测中也比前置++ 慢0.5倍左右(UOJ 上自定义测试)

    3.3 数组优化

    1、不要开bool,所有bool改成char,int是最快的(原因不明)。
    2、在最大值50000*50000的时候用unsigned代替long long
    3、对于多维数组,用到乘法优化寻址

    // Code A
    for(i=1;i<=n;i++)
        ans+=A[x][y][z][i];
    // Code B
    int *p=A[x][y][z];
    for(i=1;i<=n;i++)
        ans+=*(p+i);
    3.4 判断优化

    if()else语句比()?():()语句要慢,逗号运算符比分号运算符要快。

    3.5 结构优化

    1.如果你要经常调用a[x],b[x],c[x]这样的数组,把她们写在同一个结构体里面会变快一些,比如f[x].a, f[x].b, f[x].c
    2.指针比下标快。

    3.7 欢迎补充

    4、卡算法/预处理

    4.1 STL优化

    STL非常慢,可以手写。

    4.2 倍增优化

    倍增表小的开前面——寻址会变快很多

    4.3 Floyd初始化
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            gra[i][j]=inf
    for(int i=1;i<=b;i++)
        gra[i][i]=0

    是比

    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            if(i==j) gra[i][j]=0;
            else gra[i][j]=inf
        }    

    快80%以上的,,因为要每次去比较。

    4.4 循环展开

    自己感受。。。

    void Init_Array(int *dest, int n)
    {
        int i;
        for(i = 0; i < n; i++)
            dest[i] = 0;
    }
    void Init_Array(int *dest, int n)
    {
        int i;
        int limit = n - 3;
        for(i = 0; i < limit; i+= 4)//每次迭代处理4个元素
        {
            dest[i] = 0;
            dest[i + 1] = 0;
            dest[i + 2] = 0;
            dest[i + 3] = 0;
        }
        for(; i < n; i++)//将剩余未处理的元素再依次初始化
            dest[i] = 0;
    }
    4.5 占坑待填。
  • 相关阅读:
    漫谈AOP开发之初探AOP及AspectJ的用法
    Spring AOP那些学术概念—通知、增强处理连接点(JoinPoint)切面(Aspect)
    深入理解Java虚拟机:OutOfMemory实战
    Java内存泄漏分析与解决方案
    漂亮回答面试官struts2的原理
    [小知识]不显示没有内容的UITableViewCell
    initWithCoder: 与initWithFrame:
    pageControl设置不居中显示,居左或居右
    Xcode中报错或警告信息整理,持续更新...
    [小技巧]阀值的使用
  • 原文地址:https://www.cnblogs.com/gwj1314/p/9444878.html
Copyright © 2011-2022 走看看