坑:快速幂中的大数乘法

小朋友,你是否有很多问号:
明明用了快速幂,为啥还是 T L E \color{#4682B4}TLE TLE

题目

快速幂||取余数
简单描述一下:求 b p   m o d   k b^p\ mod\ k bp mod k

一般人会利用 ( a ⋅ b ) %   c   = ( a % c ) ⋅ ( b % c ) % c (a\cdot b)\%\ c\ =(a\%c)\cdot(b\%c)\%c (ab)% c =(a%c)(b%c)%c 这个性质,在循环内部取余,防止结果太大爆掉。但是 Python 自带高精度啊,咱有恃无恐,所以直接调用 fastPow(a, b)%k 来计算结果。然后就妥妥 T L E \color{#4682B4}TLE TLE 了。

为啥呢?因为快速幂 O ( l o g   n ) O(log\ n) O(log n) 复杂度的前提是 乘法运算是常数时间
高精度虽然不会爆掉,但是它的乘法是 大数乘法 ,并不是常数时间。

来做个实验:

import timeit


def pow(a, b):
    p = 1
    for i in range(b):
        p *= a
    return p


def fastPow(a, b):
    p = 1
    while b != 0:
        if b & 1:
            p *= a
        a *= a
        b >>= 1
    return p


t1 = timeit.default_timer()
a = pow(1, 999999)
t2 = timeit.default_timer()
a = fastPow(3, 999999)
t3 = timeit.default_timer()
print('{:.6f}'.format(t2-t1))
print('{:.6f}'.format(t3-t2))

结果如下:

0.030459
0.186064

“神奇” 的现象出现了:
快速幂比朴素算法还慢好多!

利用内建函数 pow

另外,这题利用 Python 内建函数 pow(b, p, k) 可以直接得到结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值