快速幂

快速幂

递归快速幂

递归

无非是一个二分的思路。我们很自然地可以得到一个递归方程:

an={an1aif n is oddan2an2if n is even but not 01if n = 0

计算a的n次方,如果n是偶数(不为0),那么就先计算a的n/2次方,然后平方;如果n是奇数,那么就先计算a的n-1次方,再乘上a;递归出口是a的0次方为1

int qpow(int a, int n)
{
    if (n == 0)
        return 1;
    else if (n & 2 == 1)
        return qpow(a, n - 1) * a;
    else
    {
        int temp = qpow(a, n / 2);
        return temp * temp;
    }
}

在实际问题中,题目常常会要求对一个大数取模,这是因为计算结果可能会非常巨大,但是在这里考察高精度又没有必要。这时我们的快速幂也应当进行取模,此时应当注意,原则是步步取模,如果MOD较大,还应当开long long

static int num;
int qpow(int a, int n)
{
    if (n == 0)
        return 1;
    else if (n & 2 == 1)
        return qpow(a, n - 1) * a%num;
    else
    {
        int temp = qpow(a, n / 2)%num;
        return temp * temp%num;
    }
}

大家知道,递归虽然简洁,但会产生额外的空间开销。我们可以把递归改写为循环,来避免对栈空间的大量占用,也就是非递归快速幂

非递归

我们换一个角度来引入非递归的快速幂。还是7的10次方,但这次,我们把10写成二进制的形式,也就是 (1010)2

现在我们要计算 7(1010)2,可以怎么做?我们很自然地想到可以把它拆分为 7(1000)27(10)2 。实际上,对于任意的整数,我们都可以把它拆成若干个 7(100...)2 的形式相乘。而这些 7(100...)2,恰好就是 717274……我们只需不断把底数平方就可以算出它们。

//非递归快速幂
static long powMod(long a, int b) {
		long ret = 1;
		while (b != 0) {
			if ((b & 1) == 1)
				ret *= a;
			b >>= 1;
			a = a * a;
		}
		return ret;
	}

这里的位运算符,>>是右移,表示把二进制数往右移一位,相当于/2;

取模版本的

static long powMod(long a, int b, final long mod) {
		long ret = 1;
		while (b != 0) {
			if ((b & 1) == 1)
				ret = ret * a % mod;
			b >>= 1;
			a = a * a % mod;
		}
		return ret % mod;
	}
posted @   QING~h  阅读(41)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· winform 绘制太阳,地球,月球 运作规律
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示

目录导航