程序玄學常數優化以及一些黑科技(持續更新)

1、讀入優化

  讀入時的速度cin<scanf<getcharpython

  咱們能夠用getchar()讀入整數git

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;
}

 2、運算優化

  一、位運算優化:乘上2的冪或除以2的冪時能夠直接用位運算進行優化緩存

  二、除法、取模優化:除法運算的耗時是乘法運算的幾倍,能不用盡可能不用,好比i/a>b能夠以換成i>a*b優化

  三、浮點數除法優化:spa

    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;

 3、針對cpu緩存的優化

    一、一維數組的數組大小盡可能開成2的冪,高維數組每一維的數組大小最好都不要開成2的冪!(狀壓dp時要尤爲注意)調試

    二、遍歷數組時最好按數組存放順序遍歷code

     For example  blog

    
  //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;

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

   三、數組的索引也是須要時間的,特別是高位數組的索引尋地址效率很低,所以咱們能夠用指針來代替數組尋址

  

//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維數組尋址)就派上用場了

     三、循環展開

      舉一個很蠢的例子

int cnt=0;
for(int i=0;i<n;i++)
    cnt++;
int cnt1=0,cnt2=0,cnt3=0,cnt4=0;
for(int i=0;i<n;i+=4)
    cnt1++,cnt2++,cnt3++,cnt4++;
int cnt=cnt1+cnt2+cnt3+cnt4;

    第二種的效率是是一種的4倍

    這裏有兩點須要注意的

    (1)循環展開通常最多展開8重,再多的話反而會使效率下降

    (2)循環展開的各條語句必定要是無關的,好比

    

int cnt=0;
for(int i=0;i<n;i+=4)
    cnt++,cnt++,cnt++,cnt++;

    這樣寫效率沒有顯著提高(由於4條語句都要用到cnt,4條語句相關)

黑科技

  

//只適用於本地調試or打表
struct
hugeint { string s; void read() { cin >>s; } void write() const { cout<<s } hugeint operator + (hugeint b) const { std::ofstream ofile("a.py"); ofile << "print(" << s << " + " << b.s << ")" << std::endl; ofile.close(); system("python a.py > output"); std::ifstream ifile("output"); hugeint ans; ifile >> ans; ifile.close(); return ans; } };
相關文章
相關標籤/搜索