Find Products of Elements of Big Array
Find Products of Elements of Big Array
A powerful array for an integer x
is the shortest sorted array of powers of two that sum up to x
. For example, the powerful array for 11 is [1, 2, 8]
.
The array big_nums
is created by concatenating the powerful arrays for every positive integer i
in ascending order: 1, 2, 3, and so forth. Thus, big_nums
starts as [1, 2, 1, 2, 4, 1, 4, 2, 4, 1, 2, 4, 8, ...]
.
You are given a 2D integer matrix queries
, where for queries[i] = [fromi, toi, modi]
you should calculate (big_nums[fromi] * big_nums[fromi + 1] * ... * big_nums[toi]) % modi
.
Return an integer array answer
such that answer[i]
is the answer to the ith
query.
Example 1:
Input: queries = [[1,3,7]]
Output: [4]
Explanation:
There is one query.
big_nums[1..3] = [2,1,2]
. The product of them is 4. The remainder of 4 under 7 is 4.
Example 2:
Input: queries = [[2,5,3],[7,7,4]]
Output: [2,2]
Explanation:
There are two queries.
First query: big_nums[2..5] = [1,2,4,1]
. The product of them is 8. The remainder of 8 under 3 is 2.
Second query: big_nums[7] = 2
. The remainder of 2 under 4 is 2.
Constraints:
1 <= queries.length <= 500
queries[i].length == 3
0 <= queries[i][0] <= queries[i][1] <= 1015
1 <= queries[i][2] <= 105
解题思路
看完了题解感觉也不是那么难,但代码超难写。赛时罚坐了 1 个多小时都没想到正解,感觉最近变笨了好多简单题都不会做。
为了方便这里规定强数组的下标从 开始,且下标为 的元素是 。因此每个询问对应的三元组 ,应有 和 。
容易知道强数组中的每个元素表示从数值 开始的每个数,在二进制下为 的位对应的 的幂。因此要求的乘积也是 的多少次幂,为此我们只需关注强数组 内次幂的总和即可。而下标 则表示从数值 到某个数 的某个二进制位内, 的数量。现在的问题是给定 如何快速求出对应的 ,即找到最小的一个 ,使得 在二进制下 的数量大于等于 。
显然可以二分出 ,那么对于二分出的某个值 如何快速知道 在二进制下 的数量?规定二分的范围是 ,其中 。对此我们可以分别统计 在第 位到第 位的 的数量。打表可以发现规律,对于第 位, 个 与 个 依次交替出现,因此第 位 的数量就是 。
对此我们可以先求出 对应的 ,及 对应的 。如果 ,先求出 在二进制下 的数量,记为 。暴力枚举 的二进制数位,当第 位是 时,令 ,如果 就累加 。
如果 ,先统计 在强数组内为 的位,具体做法为先求出 在二进制下 的数量 ,暴力枚举 的二进制数位,当第 位是 时,令 ,如果 就累加 。同理统计 在强数组内为 的位,具体做法为先求出 在二进制下 的数量 ,暴力枚举 的二进制数位,当第 位是 时,令 ,如果 就累加 。最后统计 为 的位的和,可以用前缀和的思想,分别求 和 为 的位的和,然后做减法。只需在求二进制下第 位为 的数量的基础上乘上 即可。
在累加了次幂后,只需用快速幂计算 的多少次幂即可。
AC 代码如下,时间复杂度为 ,其中 :
class Solution {
public:
vector<int> findProductsOfElements(vector<vector<long long>>& queries) {
vector<int> ans;
for (auto &p : queries) {
p[0]++, p[1]++;
function<long long(long long)> get = [&](long long x) {
x++;
long long s = 0;
for (int i = 0; i <= 49; i++) {
s += x / (1ll << i + 1) * (1ll << i);
if (x % (1ll << i + 1) > 1ll << i) s += x % (1ll << i);
}
return s;
};
function<long long(long long)> find = [&](long long x) {
long long l = 0, r = 1e15;
while (l < r) {
long long mid = l + r >> 1;
if (get(mid) >= x) r = mid;
else l = mid + 1;
}
return l;
};
function<int(int, long long, int)> qmi = [&](int a, long long k, int p) {
int ret = 1 % p;
while (k) {
if (k & 1) ret = 1ll * ret * a % p;
a = 1ll * a * a % p;
k >>= 1;
}
return ret;
};
long long l = find(p[0]), r = find(p[1]);
if (l == r) {
long long s = 0, c = get(l - 1);
for (int i = 0; i <= 49; i++) {
if (l >> i & 1) {
c++;
if (c >= p[0] && c <= p[1]) s += i;
}
}
ans.push_back(qmi(2, s, p[2]));
}
else {
long long s = 0, c = get(l - 1);
for (int i = 0; i <= 49; i++) {
if (l >> i & 1) {
c++;
if (c >= p[0]) s += i;
}
}
c = get(r - 1);
for (int i = 0; i <= 49; i++) {
if (r >> i & 1) {
c++;
if (c <= p[1]) s += i;
}
}
function<long long(long long)> get = [&](long long x) {
x++;
long long s = 0;
for (int i = 0; i <= 49; i++) {
long long c = x / (1ll << i + 1) * (1ll << i);
if (x % (1ll << i + 1) > 1ll << i) c += x % (1ll << i);
s += i * c;
}
return s;
};
if (l + 1 <= r - 1) s += get(r - 1) - get(l);
ans.push_back(qmi(2, s, p[2]));
}
}
return ans;
}
};
参考资料
第 130 场力扣夜喵双周赛 - 力扣(LeetCode):https://leetcode.cn/circle/discuss/FpYgO6/view/L5Vk47/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/18189595
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2022-05-13 构造数组
2022-05-13 更多奇怪的照片