程序玄学常数优化

一、读入优化

  读入时的速度cin<scanf<getchar

  我们可以用getchar()读入整数

inline int read(){
    int num=0;
    char c;
    while(isspace(c=get_char()));
    while(num=num*10+c-48,isdigit(c=get_char()));
    return num;
}

  fread是直接对二进制文件进行读入,速度更快

const int MAXBUF = 100000;
char buf[MAXBUF], *ps = buf, *pe = buf+1;
inline void rnext()
{
    if(++ps == pe)
        pe = (ps = buf)+fread(buf,sizeof(char),sizeof(buf)/sizeof(char),stdin);
}

template <class T>
inline bool in(T &ans)
{
    ans = 0;
    T f = 1;
    if(ps == pe) return false;//EOF
    do{
        rnext();
        if('-' == *ps) f = -1;
    }while(!isdigit(*ps) && ps != pe);
    if(ps == pe) return false;//EOF
    do
    {
        ans = ans*10+*ps-48;
        rnext();
    }while(isdigit(*ps) && ps != pe);
    ans *= f;
    return true;
}

 二、运算优化

  1、位运算优化:乘上2的幂或除以2的幂时可以直接用位运算进行优化

  2、除法、取模优化:除法运算的耗时是乘法运算的几倍,能不用尽量不用,比如i/a>b可以以换成i>a*b

  3、浮点数除法优化:

    float a,b,c;
    init(a,b,c);
    a/=c;
    b/=c;

    可以换成

    float a,b,c;
    init(a,b,c);
    float d=1/c;
    a*=d;
    c*=d;

 三、针对cpu缓存的优化

    1、一维数组的数组大小尽量开成2的幂,高维数组每一维的数组大小最好都不要开成2的幂!(状压dp时要尤其注意)

    2、遍历数组时最好按数组存放顺序遍历

     For example  

    
  //first
  for(int i=0;i<n;i++) for(int j=0;j<m;j++) a[i][j]*=2;
    
  //second
  for(int i=0;i<m;i++) for(int j=0;j<n;j++) a[j][i]*=2;

    第一种比第二种效率快得多

   3、数组的索引也是需要时间的,特别是高位数组的索引寻地址效率很低,因此我们可以用指针来代替数组寻址

  

//first
int a[55][65][75][85];
int main()
{
     int *p=&a[0][0][0][0];
     for(int i1=0;i1<55;i1++)
        for(int i2=0;i2<65;i2++)
            for(int i3=0;i3<75;i3++)
                for(int i4=0;i4<85;i4++)
                       (*(p++))++;
}
//second
int a[55][65][75][85];
int main()
{
     for(int i1=0;i1<55;i1++)
     {
        int (*p)[65][75][85]=a[i1];
        for(int i2=0;i2<65;i2++)
            for(int i3=0;i3<75;i3++)
                for(int i4=0;i4<85;i4++)
                       p[i2][i3][i4]++;
      }
} 
//third
int a[55][65][75][85];
int main()
{
     for(int i1=0;i1<55;i1++)
        for(int i2=0;i2<65;i2++)
            for(int i3=0;i3<75;i3++)
                for(int i4=0;i4<85;i4++)
                       a[i1][i2][i3][i4]++
} 

    很明显,效率上第一种>第二种>第三种,但很多时候并不是单纯的按顺序访问数组,这种时候第二种写法(只需要对3维数组寻址)就派上用场了

 

猜你喜欢

转载自www.cnblogs.com/unnamed05/p/10087795.html