我想知道这段代码的时间复杂性是俄罗斯农民实施
unsigned long long int russian(unsigned long long int a, unsigned long long int b) {
unsigned long long int res = 0;
while (b > 0) {
if (b & 1)
res = res + a;
a <<= 1;
b >>= 1;
}
return res % mod;
}
据我所知,我认为其时间复杂度为 lg2b 或 lg2a (取决于我们选择 a 或 b )。任何专家评论?
答案 0 :(得分:3)
您提供的代码片段的时间复杂度当然是O(1)
,因为它可以花费多长时间的上限,并且永远不会超过任何输入的上限。
据推测,这不是你实际要问的问题的答案。实际上有几个不同的东西你可能真正感兴趣,它们实际上都有不同的答案。
(另外,既然你似乎试图进行模块化乘法运算,你真的应该减少循环中里面的所有相关数量,这样你就不会溢出,所以你可以使用-
代替%
)
您可能对准确估计挂钟时间感兴趣。获得这个实际上需要收集一些经验数据,但它可能看起来像
A + B bitlength(b) + C popcount(b)
对于某些常量popcount
,1
和A
,(B
是二进制扩展中C
的个数)。但是,CPU硬件实际上相当复杂,实际上可能非常需要对上面的第三项进行良好估计,因为分支预测硬件可能会做一些奇怪的事情。
A
,B
和C
可能不是常数;它们在某种程度上取决于这个函数是否被内联,以及围绕它使用的地方的代码类型。
现在,您可能需要一个更抽象的答案,其中b
可以是任意大小,而不是约束为unsigned long long
的大小,并且想要计算算术运算的数量。这显然只是b
的位长,或者如评论所示,O(lg(b))
。 (其中lg
是日志库2)
现在,您可能实际上不仅对算术运算感兴趣,而且对成本感兴趣。并且可能对a
具有任意大小而不是约束为unsigned long long
感兴趣。一个有用的度量单位是位操作。例如在N
位数上向左移1,应该花费O(N)
位操作。
我非常确定循环适用于O(lg(a)lg(b)+lg(b)^2)
位操作。 (这不包括您之后执行的%
操作)