做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

原文地址:https://www.cnblogs.com/gosick/p/9484087.html

时间: 2024-11-05 13:40:06

做OI题时的一些常用的常数优化小技巧的相关文章

26个常用易忘CSS小技巧

收集于平时常用但易忘的CSS实现方法,如有遗漏或补充,还请指正! 解决inline-block元素设置overflow:hidden属性导致相邻行内元素向下偏移.wrap {display: inline-block;overflow: hiddenvertical-align: bottom}复制代码超出部分显示省略号// 单行文本.wrap {overflow:hidden;/超出部分隐藏/text-overflow:ellipsis;/超出部分显示省略号/white-space:nowra

IAR常用快捷键和使用小技巧

1.复制和粘贴几行的部分代码 需求:有时候我们需要复制几行代码的后半部分,不需要复制前半部分.方法:按住Alt键,再用鼠标拖动就可以复制和粘贴后半部分 2.复制一行 复制一行的时候,我们一般是从最后开始往前面复制,在软件中我们可以从上一行的最后开始复制(如下图所示),这样粘贴的时候只需要从放在最后就可以粘贴到下一行了,可能说的比较绕口,大家试一试就知道方便之处了.(事实上,多行代码也可以这样操作,word中也是一样的!) 3.常用快捷键 帮助文档:F1 Make:F7 烧录程序:Ctrl + D

postfix 常用命令及使用小技巧

mailq    查询邮件队列 postsuper -d ALL     删除队列所有邮件

在使用R做数据挖掘时,最常用的数据结构莫过于dataframe了,下面列出几种常见的dataframe的操作方法

原网址 http://blog.sina.com.cn/s/blog_6bb07f83010152z0.html 在使用R做数据挖掘时,最常用的数据结构莫过于dataframe了,下面列出几种常见的dataframe的操作方法.1.查看数据 head(dataframe) # 查看数据前10行tail(dataframe) # 查看数据后10行 2.合并数据(1)data.frame(x,y)x,y是dataframe或者一列数据,x和y的行数一样,该操作得到一个新的dataframe,该dat

做预解释题的一点小方法和小技巧

在JavaScript中的函数理解中预解释是一个比较难懂的话题.原理虽然简单,寥寥数言,但其内涵却有深意,精髓难懂.如何在轻松活跃的头脑中将它学会,现在针对我在学习中的一点小窍门给大家分享一下,希望能给大家一些帮助: 万事需遵循"原理"--"预解释"无节操和"this"指向:(可先看例题解析然后结合原理进行学习) (感谢蕾蕾老师给归纳的预解释无节操原理:) 如果函数传参数则先于以下执行,就相当于在函数私有作用域下var了一个变量:根据作用域原理,

拥有梦想的人不做选择题,他们只做证明题

是安于现在的生活并且学着享受庸常,还是甘冒下坠的风险振翅飞往远方? 这是我最近经常看到的问题.说实话,我也觉得非常惊奇,竟然有那么多人,觉得现实在一点点埋葬自己的梦想,同时又没有足够的勇气跨出一步.每次说到看不到的山那头,海的那一端,总有无数颗小心在各个地方黯然破碎.仿佛一夜之间经过了四十个星球,却没有一个星星上能种出玫瑰花来. 人们写信来,索要帮助和建议.但是我又能做什么呢?我的人生是我的人生,我的经验是我的经验,未必对你有用.况且,我安于这样的生活,命运如此安排,而换做别人,怕是不能把这其中

ACM做题小技巧

1.一般用C语言节约空间,要用C++库函数或STL时才用C++; cout.cin和printf.scanf最好不要混用. 大数据输入输出时最好不要用cin.cout,防止超时. 2.有时候int型不够用,可以用long long或__int64型(两个下划线__). 值类型表示值介于 -2^63 ( -9,223,372,036,854,775,808) 到2^63-1(+9,223,372,036,854,775,807 )之间的整数. printf("%I64d",a); //_

Nginx做负载均衡时session共享问题详解

用nginx做负载均衡时,同一个IP访问同一个页面会被分配到不同的服务器上,如果session不同步的话,就会出现很多问题,比如说最常见的登录状态. 再者Nginx连接Memcached集群时,Nignx的请求从memcached服务器中根据key获得了value则直接返回value,如果没有获得到value则去MySQL中查询再返回. location / { set $memcached_key "$request_uri"; #设置请求memcached服务器的key memca

关于有默认值的字段在用EF做插入操作时的思考

今天在用EF做插入操作的时候发现数据库中一个datetime类型的字段(CreateDate)的值居然全部为null.于是赶紧看表结构发现CreateDate字段居然是允许为空的. 虽然为空,但是设置了默认值getdate(),按说不应该为null的.于是开始测试. 字段允许Null值的情况 Users表结构如下: 假如一个字段有了默认值,并且又允许为Null,在做插入操作时会发生什么? 如上图中的表结构,CreateDate是允许为null的,而又有默认值getdate().这样在用传统SQL