• 快速幂取模&快速乘取模


    快速幂取模

    即快速求出(a^b)mod c 的值。由于当a、b的值非常大时直接求a^b可能造成溢出,并且效率低。

    思路

    原理就是基于(a*b \% c = ((a \% c)*(b \% c))\% c),(a^b \% c = (a \% c)^b \% c)公式。

    求解快速幂:

    设指数b用二进制表示为(b = (b_n b_{n-1}...b_2b_1b_0)_2)

    (b = b_0 + b_1*2^1 + b_2*2^2+...+b_{n-1}*2^{n-1} + b_n*2^n)

    (a^b = a^{b_0 + b_1*2^1 + b_2*2^2+...+b_{n-1}*2^{n-1} + b_n*2^n} = a^{b0}*a^{b_1*2^1}*a^{b_2*2^2} *...*a^{b_{n-1}*2^{n-1}} * a^{b_n*2^n})

    (a^b \% c = a^{b0}*a^{b_1*2^1}*a^{b_2*2^2} *...*a^{b_{n-1}*2^{n-1}} * a^{b_n*2^n} \% c)

    (K_n = (a^{b_n*2^n})\%c),求Kn的话,当bn=0时Kn=1,bn=1时(Kn=(a^{2^n})\%c),因此再考虑计算((a^{2^n})\%c)

    ((a^{2^n})\%c = [(a^{2^{n-1}}\%c)*(a^{2^{n-1}}\%c)]\%c)由此递推。

    代码

    python

    def quick_powmod(a, b, c):
        a = a % c
        ans = 1 # 存放结果
        while b != 0:
            if b & 1: # 二进制与
                ans = (ans * a) % c
            a = (a * a) % c # 取模是防止溢出
            b >>= 1 # 二进制向右移动一位
        return ans
    

    例如a=2 b=10 c=3,b的二进制表示为1010。

    (2^{10} = 2^{0+ 1*2^1+0*2^2+1*2^3}),b的二进制位从右往左取,为0时,累乘a,为1时,将累乘结果乘到ans里。

    快速乘取模

    使用二进制将乘法转换为加法。

    思路

    与快速幂取模类似,将一个乘数转换为二进制计算。

    例如(20*14 = 20*(1110)_2 = 20*2^0*0 + 20*2^1*1+20*2^2*1+20*2^3*1)

    代码

    Python

    def quick_mulmod(a, b, c):
        ans = 0
        a = a % c
        while b != 0:
            if b & 1 :
                ans = (ans + a) % c
            a = (2*a) % c
            b >>= 1
        return ans
    

    乍一看还是很不好懂的,举个例子推导一遍就明白了。

  • 相关阅读:
    springMVC数据绑定入门
    网易云课堂js学习笔记
    Java MyBatis insert数据库数据后返回主键
    (转)关于离职
    mybatis异常:Caused by: java.lang.IllegalArgumentException: Result Maps collection already contains value for。。。。。。
    tomcat端口号被占用的问题
    tomcat中catalina是什么
    通过代码实现创建、删除、文件的读、写
    HNOI2008玩具装箱 斜率优化
    [ZJOI2008]骑士
  • 原文地址:https://www.cnblogs.com/KRDecad3/p/11603873.html
Copyright © 2020-2023  润新知