所谓“卡常数”的常数到底指什么?

时间复杂度里被省略的常数。


zex orz!

写了这篇文章,解决大家一些普遍存在的问题,列举一些可能出现的疑问并一一解答,指出一些对“常数”的误解,给高二学长zex一个惊喜

我星期三的时候还不知道什么是“常数”,目前对渐进学了解甚微

所以如果我说错了可以喷我


概述

众所周知,时间复杂度里面是没有常数的,因为常数项系数在足够的数据规模下,存在感并不强。

比如说你去推出了杜教筛的式子

s(n)=\sum_{i=1}^{n}f(i)                 g(1)s(n)=\sum_{i=1}^{n}h(i)-\sum_{d=2}^{n}g(d)s(\lfloor\frac{n}{d}\rfloor)

然后你惊喜的发现,1e10的数据,f你只用预处理到5e9就行了。

hhhhhhhhhhhhhh

因此,我们不会看见O(n/2)这种东西。

O是一个函数,函数有自变量,因变量和常数。当自变量达到一定数量级时,常数自然微乎其微。我们平时看到一个一次函数图像,y=2x似乎比y=x陡峭得多,你赞叹这就是常数的力量,但其实是你格局太小了。

 (微软数学只画了一点点,如果你有更好的画图工具可以试试把这张图持续缩小。)

虽然数量级很小,但是已经可以隐约看出常数阶和平方阶的区别了。

我们有一个复杂度的排行:

O(1)常数阶 < O(logn)对数阶 < O(n)线性阶 < O(n^2)平方阶 < O(n^3)(立方阶) < O(2^n) (指数阶)

常数是最渺小的。

所以,我们一般在算时间复杂度时不会考虑常数。而且就算你把复杂度优化到了常数阶,那算啥本事?不毒瘤的出题人都不会考你这个,少做几个操作谁不会,你把循环次数优化了才是真本事。

但是你不考虑,不代表所有题目都不会卡你。

来看这两段代码:

第二段的实际复杂度是第一段的3倍,但在大O里表示,都是O(n)。

  • 假设你是一个小学生,学校停电了,让你来当评测机。你计算a++的时间是1秒,大多数善良的老师们会给你几节课的时间来执行每个同学的代码,但就是有个老师输入n=6e5非要你1.2M秒算出来。于是,第一段代码过了,而第二段没过,尽管他们的渐进学复杂度是一样的。
  • 又或者刚才提到的杜教筛,(先不管5e9你是怎么存下来的,感兴趣自己了解递归)出题人精确计算后决定卡你线性筛,给的时间大概够预处理到7e9的样子(区别真的大吗???)然后你要是不用杜教筛那个式子呢,你就被卡爆了。

现在来分析一下“卡常数”里的情感色彩。

在这两个例子里,虽然都是卡常的操作,但显然情感不一样。eg1里,大家都公认常数阶是不值一考的,但是他非要卡,就像这个老师一样,让一个小学生多磨蹭一会又怎样,他非要这么抠门,让人感受到的就是这个人十分讨厌。但是eg2,大家都知道推出杜教筛是十分不容易的,这是一个很高级,很有价值的算法,不能与相对低俗的线性筛沦为一体混为一谈。所以大家需要明白的是,论一个人的行为要从其目的出发,不能停留在行为表面。

所以,eg2到底算不算卡常,可以从道德层面分析一下。

(另外,杜教筛其实不是这样做的,只是举个例子,他所精简的复杂度不是常数阶的。但是大千世界,你一定会遇到那样的情况,比如说,KMP)

那么,我们就来看一些常见的疑问吧。


“常数是指用渐进学算出来复杂度一样的情况下,用来衡量一个算法速度快慢的概念”

这是一个由常数的作用引申出来的定义。这个定义是可行的,但他不是常数真正的定义。

“我们只会说这种算法的常数小于另外一种,而不会像数学里那样具体求出这个‘数’的值”

节选的这两段话很显然是教新手如何混OI圈的。

确实,我们不会无聊到去算一个程序大O里省略掉的常数,但常数确实是一个真实存在的值,而不是一个“相对的概念”。

这样的解释显然会让一头雾水的人更加一头雾水。但不得不承认的是,你没有必要每次跟谁都去解释上文所述。所以,如果你的目的就是让他能正常地与OIer们交流的话,这样解释是一个不错的选择。


“是因为他就像复杂度里的常数一样才叫这个名字,还是他本身与常数有什么关系?”

“就可以理解成一个比喻”

显然不是一个比喻。

本来就是指时间复杂度里的常数。


“但是因为实际因素的差异,代码实现会造成时间差异”

是这样的。

还是上文的例子,如果这个小学生评测机要1.1秒才能计算a++,显然是会有时间差异的。而在常数阶以上的,误差完全可以忽略。因此按照上面大多数人对常数的定义,这样的误差也算在常数里。


“queue就带一些常数”

在stl这种计算机帮你写代码的东西里,常数的事自然是他说了算。cin,scanf与快读之类的也是同理。

“KMP没啥常数”

KMP比一般匹配节省一些操作,因此常数也是优化的。


“计算机内部节省了基本运算的次数,也就减少了常数”

是的,因为常数是时间复杂度里的


“他跟真正的,大家能够理解的常数有没有关系呢?”

“没啥关系吧”

当然是有关系的,他在时间复杂度里是以常数的形式体现的。


“杜教筛预处理5e6和6e6的区别,算是常数的区别吗?”

你要说,那肯定也是算的。

只是,这种情况只是千千万常数的很小一种情况。你确定你是真的理解了什么是常数?你只是不知道常数是时间复杂度里的,因此需要把他具象化来理解吧。


如果有写的不对,也很正常了

希望对你有帮助

zex orz!

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值