|
| 1 | +--- |
| 2 | +title: 2438.二的幂数组中查询范围内的乘积:模拟(前缀和可选) |
| 3 | +date: 2025-08-11 21:48:30 |
| 4 | +tags: [题解, LeetCode, 中等, 位运算, 数组, 前缀和] |
| 5 | +categories: [题解, LeetCode] |
| 6 | +--- |
| 7 | + |
| 8 | +# 【LetMeFly】2438.二的幂数组中查询范围内的乘积:模拟(前缀和可选) |
| 9 | + |
| 10 | +力扣题目链接:[https://leetcode.cn/problems/range-product-queries-of-powers/](https://leetcode.cn/problems/range-product-queries-of-powers/) |
| 11 | + |
| 12 | +<p>给你一个正整数 <code>n</code> ,你需要找到一个下标从 <strong>0</strong> 开始的数组 <code>powers</code> ,它包含 <strong>最少</strong> 数目的 <code>2</code> 的幂,且它们的和为 <code>n</code> 。<code>powers</code> 数组是 <strong>非递减</strong> 顺序的。根据前面描述,构造 <code>powers</code> 数组的方法是唯一的。</p> |
| 13 | + |
| 14 | +<p>同时给你一个下标从 <strong>0</strong> 开始的二维整数数组 <code>queries</code> ,其中 <code>queries[i] = [left<sub>i</sub>, right<sub>i</sub>]</code> ,其中 <code>queries[i]</code> 表示请你求出满足 <code>left<sub>i</sub> <= j <= right<sub>i</sub></code> 的所有 <code>powers[j]</code> 的乘积。</p> |
| 15 | + |
| 16 | +<p>请你返回一个数组<em> </em><code>answers</code> ,长度与<em> </em><code>queries</code> 的长度相同,其中<em> </em><code>answers[i]</code>是第<em> </em><code>i</code> 个查询的答案。由于查询的结果可能非常大,请你将每个 <code>answers[i]</code> 都对 <code>10<sup>9</sup> + 7</code> <strong>取余</strong> 。</p> |
| 17 | + |
| 18 | +<p> </p> |
| 19 | + |
| 20 | +<p><strong>示例 1:</strong></p> |
| 21 | + |
| 22 | +<pre><b>输入:</b>n = 15, queries = [[0,1],[2,2],[0,3]] |
| 23 | +<b>输出:</b>[2,4,64] |
| 24 | +<strong>解释:</strong> |
| 25 | +对于 n = 15 ,得到 powers = [1,2,4,8] 。没法得到元素数目更少的数组。 |
| 26 | +第 1 个查询的答案:powers[0] * powers[1] = 1 * 2 = 2 。 |
| 27 | +第 2 个查询的答案:powers[2] = 4 。 |
| 28 | +第 3 个查询的答案:powers[0] * powers[1] * powers[2] * powers[3] = 1 * 2 * 4 * 8 = 64 。 |
| 29 | +每个答案对 10<sup>9</sup> + 7 得到的结果都相同,所以返回 [2,4,64] 。 |
| 30 | +</pre> |
| 31 | + |
| 32 | +<p><strong>示例 2:</strong></p> |
| 33 | + |
| 34 | +<pre><b>输入:</b>n = 2, queries = [[0,0]] |
| 35 | +<b>输出:</b>[2] |
| 36 | +<strong>解释:</strong> |
| 37 | +对于 n = 2, powers = [2] 。 |
| 38 | +唯一一个查询的答案是 powers[0] = 2 。答案对 10<sup>9</sup> + 7 取余后结果相同,所以返回 [2] 。 |
| 39 | +</pre> |
| 40 | + |
| 41 | +<p> </p> |
| 42 | + |
| 43 | +<p><strong>提示:</strong></p> |
| 44 | + |
| 45 | +<ul> |
| 46 | + <li><code>1 <= n <= 10<sup>9</sup></code></li> |
| 47 | + <li><code>1 <= queries.length <= 10<sup>5</sup></code></li> |
| 48 | + <li><code>0 <= start<sub>i</sub> <= end<sub>i</sub> < powers.length</code></li> |
| 49 | +</ul> |
| 50 | + |
| 51 | + |
| 52 | + |
| 53 | +## 解题方法:模拟 |
| 54 | + |
| 55 | +**如何将$n$拆成递增的2的幂组成的数组powers** |
| 56 | + |
| 57 | +很简单,$n$二进制下哪一位(记为$i$)是$1$就将$1\lt \lt i$按顺序加入powers数组。 |
| 58 | + |
| 59 | +**对于一个query如何求出对应answer** |
| 60 | + |
| 61 | +两种方法: |
| 62 | + |
| 63 | +1. 直接暴力从query[0]累乘到query[1]并随时取模 |
| 64 | +2. 前缀和的思想,使用数组perfix[j]代表$\prod_{0}^{j-1}powers[i]$ |
| 65 | + |
| 66 | +直接暴力的方法并不会很耗时,因为powers数组中最多30个元素; |
| 67 | + |
| 68 | +前缀和的思想适用于Python这种自带大整数的编程语言,否则取模后的相除还需要取逆元。 |
| 69 | + |
| 70 | +### 时空复杂度分析 |
| 71 | + |
| 72 | +暴力: |
| 73 | + |
| 74 | ++ 时间复杂度$O(\log n\times len(queries))$ |
| 75 | ++ 空间复杂度$O(\log n)$ |
| 76 | + |
| 77 | +前缀和 |
| 78 | + |
| 79 | ++ 时间复杂度$O(\log n + len(queries))$ |
| 80 | ++ 空间复杂度$O(\log n)$ |
| 81 | + |
| 82 | +### AC代码 |
| 83 | + |
| 84 | +#### C++ |
| 85 | + |
| 86 | +```cpp |
| 87 | +/* |
| 88 | + * @Author: LetMeFly |
| 89 | + * @Date: 2025-08-11 18:41:58 |
| 90 | + * @LastEditors: LetMeFly.xyz |
| 91 | + * @LastEditTime: 2025-08-11 21:43:41 |
| 92 | + */ |
| 93 | +typedef long long ll; |
| 94 | +const ll MOD = 1e9 + 7; |
| 95 | + |
| 96 | +class Solution { |
| 97 | +public: |
| 98 | + vector<int> productQueries(int n, vector<vector<int>>& queries) { |
| 99 | + vector<int> pows; |
| 100 | + int th = 0; |
| 101 | + while (n) { |
| 102 | + if (n & 1) { |
| 103 | + pows.push_back(1 << th); |
| 104 | + } |
| 105 | + n >>= 1; |
| 106 | + th++; |
| 107 | + } |
| 108 | + vector<int> ans(queries.size()); |
| 109 | + for (int i = 0; i < queries.size(); i++) { |
| 110 | + ll thisVal = 1; |
| 111 | + for (int j = queries[i][0]; j <= queries[i][1]; j++) { |
| 112 | + thisVal = thisVal * pows[j] % MOD; |
| 113 | + } |
| 114 | + ans[i] = thisVal; |
| 115 | + } |
| 116 | + return ans; |
| 117 | + } |
| 118 | +}; |
| 119 | +``` |
| 120 | +
|
| 121 | +#### Python |
| 122 | +
|
| 123 | +```python |
| 124 | +''' |
| 125 | +Author: LetMeFly |
| 126 | +Date: 2025-08-11 21:37:10 |
| 127 | +LastEditors: LetMeFly.xyz |
| 128 | +LastEditTime: 2025-08-11 21:46:52 |
| 129 | +''' |
| 130 | +from typing import List |
| 131 | +
|
| 132 | +class Solution: |
| 133 | + def productQueries(self, n: int, queries: List[List[int]]) -> List[int]: |
| 134 | + pows = [] |
| 135 | + th = 0 |
| 136 | + while n: |
| 137 | + if n & 1: |
| 138 | + pows.append(1 << th) |
| 139 | + th += 1 |
| 140 | + n >>= 1 |
| 141 | + perfix = [1] * (len(pows) + 1) |
| 142 | + for i in range(1, len(pows) + 1): |
| 143 | + perfix[i] = perfix[i - 1] * pows[i - 1] |
| 144 | + return [perfix[q[1] + 1] // perfix[q[0]] % 1000000007 for q in queries] |
| 145 | +``` |
| 146 | + |
| 147 | +> 同步发文于[CSDN](https://letmefly.blog.csdn.net/article/details/150227536)和我的[个人博客](https://blog.letmefly.xyz/),原创不易,转载经作者同意后请附上[原文链接](https://blog.letmefly.xyz/2025/08/11/LeetCode%202438.%E4%BA%8C%E7%9A%84%E5%B9%82%E6%95%B0%E7%BB%84%E4%B8%AD%E6%9F%A5%E8%AF%A2%E8%8C%83%E5%9B%B4%E5%86%85%E7%9A%84%E4%B9%98%E7%A7%AF/)哦~ |
| 148 | +> |
| 149 | +> 千篇源码题解[已开源](https://github.com/LetMeFly666/LeetCode) |
0 commit comments