zoukankan      html  css  js  c++  java
  • 浅谈快速幂/快速乘

    浅谈快速幂

    这篇随笔简单讲解一下数学问题种快速幂的实现原理及实现。


    快速幂的用途

    顾名思义,快速幂就是很快速的幂运算,试想当你面对一个问题:求(a^b)的时候,你的第一反应是开(long long)然后用(for)循环一点一点求。那么你就已经会了幂运算的(O(b))算法。按常理来讲,这样的算法已经够用了,但是遇到一些卡时间的题目的时候还是会(T),于是快速幂应运而生。简单地说,快速幂就是一种复杂度为(O(logb))的求幂运算的算法。


    快速幂的实现原理

    因为快速幂的时间复杂度是(O(logb))的,所以我们自然而然地想到了二进制及位运算。这是显然的,我们知道,一个整数可以被拆分成若干个(2^k)的和。那么类比一下,对于一个幂运算问题(a^b),我们可以把(b)二进制分解,成为若干个(2^k)的和,那么对应下来就是这些和的幂的乘积。

    举个例子:

    求解问题:(3^{42})

    第一步,将42二进制拆分:

    [(42)_{10}=(101010)_2=1 imes 2^5+0 imes 2^4+cdots+0 imes 2^0 ]

    那么,(3^{42})就变成了:

    [3^{42}=3^{1×32 + 0×16 + 1×8 + 0×4 + 1×2 + 0×1} ]

    所以,我们就有了这样的一个原理:

    在求解(a^b)的时候,如果(b)是奇数,那么原式就是:(a imes a^{b-1})

    同理,如果(b)是偶数,那么原式就可以变成:(a^{bdiv2} imes a^{bdiv 2}).

    这是一种倍增的思想,这样我们就把原来的(O(b))算法就被优化成了(O(logb))的算法。

    这就是快速幂的实现原理。


    快速幂的代码实现

    根据我们刚刚学习的快速幂的实现原理,我们很容易发现,这个东西可以用递归来实现。代码如下:

    int qpow(int a,int b)
    {
        if(!b)
            return 1;
        else if(b&1)
            return a*qpow(a,b-1);
        else
        {
            int t=qpow(a,b>>1);
            return t*t;
        }
    }
    

    但是,学过递归的小伙伴应该知道,递归的常数巨大无比。所以上面的代码并不是一个资深(OIer)会选择的东西。

    那快速幂怎么写保证常数不大呢?

    我们采用一种迭代的写法:

    我们会发现,无论(b)为何值,它在快速幂迭代的过程中要么(-1),要么(div 2)。但无论它采用了以上的哪一种操作,都必会有一个时刻,(b=1)。,也就是说,(b)在迭代的过程中,至少会有一个时刻(b)为奇数。

    那么我们考虑,我们完全可以在(bdiv 2)的迭代中,先不使迭代的结果影响到答案,而是先把迭代的结果储存下来,然后等到(b)为奇数的时候统一加到答案里去。这样就省去了繁琐的递归和记录答案的过程,保证了常数小,而且维护了答案的正确性。

    代码如下:

    int qpow(int a,int b)
    {
        int ret=1;
        while(b>0)
        {
            if(b&1)
                ret*=a;
            a*=a;
            b>>=1;
            }
        }
        return ret;
    }
    

    快速乘的原理及其代码实现

    其实,就是把快速幂的乘法运算变成了加法运算。

    原理超级容易理解...

    模板也大同小异:

    ll qmult(ll a,ll b)
    {
        ll ret=0;
        while(b>0)
        {
            if(b&1)
                ret=(ret+a)%mod;
            a=(a+a)%mod;
            b>>=1;
        }
        return ret;
    }
    
  • 相关阅读:
    线性表链式存储方式的C语言实现
    线性表顺序存储方式的C语言实现
    抽象数据类型Triplet的C语言实现
    Python之装饰器
    Django-auth(认证系统)
    Django-中间件
    Django-form表单
    Python cookie、session和自定义分页
    Django 使用ajax上传文件
    Python之迭代器和生成器
  • 原文地址:https://www.cnblogs.com/fusiwei/p/11599881.html
Copyright © 2011-2022 走看看