做OI题时的一些常用的常数优化小技巧

Posted gosick

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了做OI题时的一些常用的常数优化小技巧相关的知识,希望对你有一定的参考价值。

  注意:本文所介绍的优化并不是算法上的优化,那个就非常复杂了,不同题目有不同的优化。笔者要说的只是一些实用的常数优化小技巧,很简单,虽然效果可能不那么明显,但在对时间复杂度要求十分苛刻的时候,这些小的优化对于帮助你成功卡常也是十分重要的。那么我们让切入正题吧。

  (1)inline放在自定义函数前

   不要问为什么,加就行了!额,这个东西好像可以让你的函数有机会被计算机执行得稍微快一点,一般放在使用次数比较多的函数前,像check(),为sort()定制的CMP()等等,当然主函数前就不要放了。。。比如下面这个例子: 

1 inline bool CMP(const int &a,const int &b){
2     return a>b;
3 }

  (2)register放在变量前

     这个可以有机会把变量申请存储在寄存器中,一般可以用来定义赋值次数较多的循环变量跑得飞快!

  (3)++i比i++快

     记住就行了,尽量用++i而不用i++,当然有特殊需要要用i++时除外。

  (4)读入优化(很重要!)

  这是针对整数的。先介绍一下原理:读入一个数时把它当作字符读比当作一个数读快,或者说用getchar(),gets()一类读比用scanf("%d",&x)要快。而读入字符时本身就是这样读的,当然就不用优化了。不要问为什么!一般会自定义一个read()函数来读取,写法有很多,这里贴上最常见的写法:

 1 inline int read()
 2 {
 3     int f=1,x=0;    //f表示符号,1为正,-1为负
 4     char ss=getchar();
 5     while(ss<0||ss>9){if(ss==-)f=-1;ss=getchar();}//跳过数字前的空格等字符
 7     while(ss>=0&&ss<=9){x=x*10+ss-0;ss=getchar();}//读到下一位ss,就把已读到的乘10,相当于全部进一位,为存ss留出空间
 9     return f*x;
10 }
11 //使用时直接x=read(),相当于scanf("%d",&x);                    

   使用读入优化在数据规模较小时优势并不明显,但在数据规模很大,比如上百万时,使用读入优化会比不使用的读取速度快上几倍。

  (5)输出优化

  既然有读入优化,自然也有输出优化。只是输出优化应用机会很少(一般只输出几个数),只有在需要输出的答案较多时才可能会用到。原理同读入优化,把原本为整数的答案转为字符(串)形式后输出。例如输出一个int型变量x,一般会写:

1 printf("%d",x);

     而用输出优化就是:

1 void put(int x)
2 {3      if(!x) return ;   
4      put(x/10);  
5      printf("%c",x%10);     //因为得从最高位到最低位输出,所以采用递归实现
7 }
8       

  (6)使用位运算符<<与>>

  这两个东西是C语言中的位运算符,什么意思呢?不会的可以百度一下,简单来说就是一个数在二进制状态下向左(右)移几位(超出的位数舍弃)后的值。比如1<<2,意思是把1的二进制左移2位后得到的值。我们知道1的二进制是1(2),左移2位,就是100(2),也就是4。那么8>>1的值是多少呢?8=1000(2),右移一位就是100(2),也就是4。也许你会惊奇地发现a<<b就等于a*2^b,a>>b就等于a/2^b。没错!这就是我们要用到它的地方。当你写a=a/2时,你也可以写成a=a>>1;a=a*2也可以写成a=a<<1,等等。    

   那么,为什么我们非要用这个位运算符呢?因为在C语言中,位运算比起加减乘除等属于较底层的操作,加减乘除其实也是通过位运算实现的,算是一种把底层操作更高级地“打包”起来,就像高级语言是由机器语言转化而来的,执行时仍然要编译为机器语言,这中间当然会花费一些不必要的时间和空间,因此越底层的操作往往越快。并且,我们可以用1<<n很方便地表示2^n,在实际操作中很有用处。

   

  初次发表博文,希望能帮到大家,如有错误,敬请指正!

2018-08-15

以上是关于做OI题时的一些常用的常数优化小技巧的主要内容,如果未能解决你的问题,请参考以下文章

常数优化

提效小技巧——记录那些不常用的代码片段

常数优化技巧

Android代码优化小技巧

Android代码优化小技巧

Android课程---Android Studio使用小技巧:提取方法代码片段