1. 题目解析与解题思路
这道GESP七级真题考察的是区间乘积问题,属于算法竞赛中的经典题型。题目给定一个包含n个正整数的序列A,要求处理m次查询,每次查询给出区间[l,r],需要计算该区间内所有元素的乘积。由于直接暴力计算在数据量大的情况下效率极低,我们需要寻找更优化的算法。
1.1 问题核心分析
区间查询问题通常有三种解决思路:
- 暴力遍历:每次查询都重新计算区间乘积,时间复杂度O(n)每次查询
- 前缀积数组:预处理前缀积数组,查询时通过除法计算区间乘积,时间复杂度O(1)每次查询
- 线段树/树状数组:适用于动态修改和查询的场景
对于本题的静态查询场景(没有修改操作),前缀积数组是最优选择。但需要注意乘积可能非常大,题目通常会要求对结果取模。
1.2 数学原理与算法选择
前缀积数组的原理基于乘法结合律:
- 预处理阶段:构建数组prefix,其中prefix[i] = a1 * a2 * ... * ai
- 查询阶段:区间[l,r]的乘积 = prefix[r] / prefix[l-1]
但直接使用除法会遇到两个问题:
- 大数溢出:乘积可能超过整数表示范围
- 模运算下的除法:需要转换为乘法逆元
因此在实际实现中,我们通常:
- 对乘积取模(如1e9+7)
- 预处理前缀积数组时直接存储模后的结果
- 使用费马小定理计算模逆元
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 代码实现与细节解析
2.1 基础实现方案
cpp复制#include <iostream>
#include <vector>
using namespace std;
const int MOD = 1e9 + 7;
vector<int> buildPrefixProduct(const vector<int>& arr) {
vector<int> prefix(arr.size() + 1, 1);
for (int i = 1; i <= arr.size(); ++i) {
prefix[i] = (1LL * prefix[i-1] * arr[i-1]) % MOD;
}
return prefix;
}
int rangeProduct(const vector<int>&
