1. 程式人生 > >程式玄學常數優化

程式玄學常數優化

一、讀入優化

  讀入時的速度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維陣列定址)就派上用場了