力扣刷题——3266. K 次乘运算后的最终数组 II

根据题意,使用模拟解法,维护一个最小堆,始终对堆的第一个元素做乘,然后每次运算后维护堆。在实现的时候保存原有的下标,可以很方便的输出答案,有实现如下:

class Solution {
public:
    vector<int> getFinalState(vector<int>& nums, int k, int multiplier) {
        int MOD = 1e9 + 7;
        vector<int> res = nums;
        if(multiplier == 1)
            return res;
        
        vector<pair<long long, int>> h;
        for(int i = 0; i < res.size(); i++)
        {
            h.emplace_back(make_pair(nums[i], i));
        }
        make_heap(h.begin(), h.end(), greater<>());
        
        while(k)
        {
            pop_heap(h.begin(), h.end(), greater<>());
            h.back().first *= multiplier;
            push_heap(h.begin(), h.end(), greater<>());
            k--;
        }

        for(int i = 0; i < nums.size(); i++)
        {
            res[h[i].second] = h[i].first % MOD;
        }
        return res;
    }
};

但是这样实现有一个问题,有时候计算堆中的元素会超过int甚至是long long型的最大值,而直接在循环里加入取模运算的话,会导致混乱。
为了避免这个问题,采取两步计算策略。首先用模拟的方法,计算答案;之后,当堆顶元素大于等于原nums中最大值temMax时,直接用数学公式计算。
因为对第一步计算完成后的堆排序后,假如用模拟的思路去计算,只是依次计算,如对下标为0的元素做乘,之后轮到下标为1的元素,直到最后,然后不断循环。这是因为在不取mod的情况下,h[i] < h[i + 1]并且h[i] * multiplier > h[h.size()]
再使用快速幂加速,有实现:

class Solution {
public:
    long long MOD = 1e9 + 7;

    vector<int> getFinalState(vector<int>& nums, int k, int multiplier) {
        vector<int> res = nums;
        if(multiplier == 1)
            return res;
        
        vector<pair<long long, int>> h;
        for(int i = 0; i < res.size(); i++)
        {
            h.emplace_back(make_pair(nums[i], i));
        }
        make_heap(h.begin(), h.end(), greater<>());
        
        int temMax = ranges::max(nums);
        while(k && h[0].first < temMax)
        {
            pop_heap(h.begin(), h.end(), greater<>());
            h.back().first *= multiplier;
            push_heap(h.begin(), h.end(), greater<>());
            k--;
        }

        sort(h.begin(), h.end());
        int t = k / nums.size();
        for(int i = 0; i < nums.size(); i++)
        {
            
            if(k % nums.size())
            {
                k--;
                res[h[i].second] = (h[i].first % MOD) * quickPow(multiplier, t + 1) % MOD;
            }
            else
                res[h[i].second] = (h[i].first % MOD) * quickPow(multiplier, t) % MOD;
        }
        return res;
    }

    long long quickPow(long long m, long long t)
    {
        long long res = 1;
        while(t)
        {
            if(t & 1)
                res = (res * m) % MOD;
            t >>= 1;
            m = (m * m) %  MOD;
        }
        return res;
    }
};
posted @ 2024-12-13 17:48  SuzumiyaYui  阅读(19)  评论(0)    收藏  举报