每天一道LeetCode-----求一个数的n次方,n是很大很大的数,n用数组存储着

这篇博客探讨了LeetCode中的 Pow(x, n) 和 Super Pow 问题,讲解如何求解大数的n次方。针对Super Pow,由于n可能超出了int范围且存储在数组中,博主提出了一种逐位处理的算法,通过不断减少n的长度并利用特定公式进行计算,直到n变为1或0。这种方法避免了直接计算大数的复杂性。" 124820173,7619246,RocketMQ高可用部署架构设计,"['架构', '分布式', 'java', '消息中间件']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Pow(x, n)

原题链接Pow(x, n)
这里写图片描述
给定一个数,求n次方。n次方可以分解成两个n/2次方相乘,所以递归即可。

class Solution {
public:
    double myPow(double x, int n) {
        bool negative = n < 0;
        double res = helper(x, n);
        return negative ? 1 / res : res;
    }
private:
    double helper(int x, int n)
    {
        if(n == 0)
            return 1;
        if(n == 1)
            return x;

        if(n % 2)
        {
            double res = helper(x, n / 2);
            return res * res * x;
        }
        else
        {
            double res = helper(x, n / 2);
            return res * res;
        }
    }
};

Super Pow

原题链接Super Pow
这里写图片描述
同样是求某个数的n次方,但是n存在数组中,如[1, 0]代表n为10。而且数组代表的n会非常大,有可能会超过int的范围,所以直接还原n然后计算n次方的方法基本是没戏了。
既然这样,就只能从每位下手,有这样一个公式

(a * b) % k = (a % k) * (b % k) % k

以数组为[1, 2, 3, 4, 5, 6, 7]为例,表示a的1234567次方,因为有

a ^ 1234567 = (a ^ 1234560) * (a ^ 7)

所以

(a ^ 1234567) % k = (((a ^ 1234560) % k) * ((a ^ 7) % k)) % k

(a ^ 1234560) % k = ((a ^ 123456) ^ 10) % k = (((a ^ 123456) % k) ^ 10 ) % k

所以

(a ^ 1234567) % k = (((((a ^ 123456) % k) ^ 10 ) % k) * ((a ^ 7) % k)) % k

a ^ n % k抽象为f(a, n)函数,那么上式可以写成

f(a, 1234567) = f(f(a, 123456), 10) * f(a, 7) % k

可以发现,每次都可以把n的最后一位去除,从而减少n,当n为1或为0时返回即可。不过注意上面的式子对于n为[0 : 10]内的数都不需要再调用f函数了,直接求就可以,也就是将外层f改为pown

f(a, 1234567) = pown(f(a, 123456), 10) * pown(a, 7) % k
class Solution {
public:
    int superPow(int a, vector<int>& b) {
        if(b.empty())
            return 1;
        int back = b.back();
        b.pop_back();
        return pown(superPow(a, b), 10) * pown(a, back) % base_;
    }
private:
    int pown(int n, int k)
    {
        /* 
         * 因为n可能很大,这里实现取模防止在for循环result * n中溢出
         * 比如result为第二次for循环后的某个数,而n为INT_MAX,乘完直接溢出
         */
        n %= base_;
        int result = 1;
        for(int i = 0; i < k; ++i)
            result = (result * n) % base_;
        return result;
    }

    const int base_ = 1337;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值