zoukankan      html  css  js  c++  java
  • 常数优化

    关于考场上优化代码常数的一些小技巧......

    常数优化

    1.读入优化

    优化程序不如常数,优化常数不如优化(IO)

    当一道题目的输入量开始变大时,这就意味我们要开始优化(IO)了。

    优化了一道题的读入后,在读入较大的情况系,大概可以快个(100-200ms)左右。

    代码如下:

    inline void Rd(int &res) {
    	res = 0;
    	int flag = 1;
    	char c;
    	while (c = getchar(), c < 48 || c > 57)if (c == '-')flag = 0;
    	do res = (res << 1) + (res << 3) + (c ^ 48);
    	while (c = getchar(), c <= 57 && c >= 48);
    	res = flag ? res : -res;
    }
    

    当然为了更快我们可以利用(fread)进行读入。

    代码如下:

    char buf[200000], *p1 = buf, *p2 = buf;
    #define getchar() p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 200000, stdin), p1 == p2) ? EOF : *p1++
    
    inline void Rd(int &res) {
    	res = 0;
    	int flag = 1;
    	char c;
    	while (c = getchar(), c < 48 || c > 57)if (c == '-')flag = 0;
    	do res = (res << 1) + (res << 3) + (c ^ 48);
    	while (c = getchar(), c <= 57 && c >= 48);
    	res = flag ? res : -res;
    }
    

    还有的是(fwrite),输出(x)

    char buff[20000000],*iter=buff,Stk[15];
    if(!X)*iter++='0';
    else {
          int O=0;
          for(; X;)Stk[++O]=(X%10)^48,X/=10;
          for(; O;)*iter++=Stk[O--];
    }
    *iter++='
    ';
    fwrite(buff,1,iter-buff,stdout);
    

    2.++i

    从所周知,循环通常有两种写法:

    for(int i=1;i<=n;i++);
    for(int i=1;i<=n;++i);
    

    而事实上,下面一行的代码比上面一行的代码快了不止一点,原因是:

    (++i)是先改变i的值即加1后再使用i的值,而(i++)是先使用i的值在改变它的值即加。

    由此,在循环中使用(++i)会比(i++)快一些。

    3.**register **

    众所周知,(register)是一个好东西,他利用了寄存器读入以及运行比普通要快的原理,请求让编译器将变量直接放入寄存器里面,以提高读取速度;

    用法:在需要多次使用的变量前加上(register)即可。

    register int a;
    

    不过,需要注意的是由于寄存器太小,通常只能寄存(8)个变量,所以在一份代码中我们用(register)修饰过的变量不能超过(8)个。

    register关键字请求让编译器将变量a直接放入寄存器里面,以提高读取速度,在C语言中register关键字修饰的变量不可以被取地址,但是c++中进行了优化。

    4.**inline **

    在c/c++中,为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别的引入了inline修饰符,表示为内联函数,栈空间就是指放置程序的局部数据(也就是函数内数据)的内存空间。在系统下,栈空间是有限的,假如频繁大量的使用就会造成因栈空间不足而导致程序出错的问题,如,函数的死循环递归调用的最终结果就是导致栈内存空间枯竭。

    (inline)的函数不能是递归函数,同时,当我们加入(inline)修饰时,我们并不能确定编译器是否将其内联,事实上决定了函数是否内联还是编译器本身,(qwq)

    也就是说,一个函数是否内联是看编译器心情的。。。。

    5.利用指针优化和取址优化

    在考试以及比赛中,我们常常会需要查询一段多维数组的值,以及修改一段多维数组的值。

    这时候,我们可以利用指针进行一些优化,以减少常数。

    例如,我们需要在(A[i][1]-A[i][n])中找一个最小值,我们可以这样打:

    int Ans=1e9;
    int *p=A[i];
    for(int i=1;i<=n;++i)Ans=min(Ans,*++p);
    return Ans;
    

    这样,我们优化了查找的常数,事实上,在数组维度很大的情况下,运行时间和内存往往会减小很多。

    同理利用取址来优化常数也是一样的,在记忆化搜索时,我们常常需要调用和修改一个数组的值:

    int dfs(int x){
        if(~dp[x])return dp[x];
        dp[x]++;
        return dp[x];
    }
    

    该成这样会快很多:

    int dfs(int x){
        int &t=dp[x];
        if(~t)return t;
        t++;
        return t;
    }
    

    以上内容帮助我们优化了一部分常数。

  • 相关阅读:
    1265 四点共面
    1003 阶乘后面0的数量
    1080 两个数的平方和
    1090 3个数和为0
    1087 1 10 100 1000
    1082 与7无关的数
    OpenLayers工作原理
    CI(持续集成)CD(持续交付)
    打包命令
    文件与目录管理重点
  • 原文地址:https://www.cnblogs.com/dsjkafdsaf/p/11379266.html
Copyright © 2011-2022 走看看