前缀和练习

本文介绍了使用Java编程语言实现的一个程序,通过Scanner读取用户输入的一组整数,计算每个数与剩余数组元素求和后乘积的结果。

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

 JAVA代码实现:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
          long[] a = new long[n+1];
         long[] sum = new long[n+1];
        long ans = 0;

        for (int i = 1; i <= n; i++) {
            a[i] = sc.nextInt();
            sum[i] = sum[i - 1] + a[i];
        }

        for (int i = 1; i <= n - 1; i++) {
            ans += a[i] * (sum[n] - sum[i]);
        }

        System.out.println(ans);
    }
}

### 关于前缀和算法的相关练习题 以下是几道经典的前缀和算法题目及其解析: #### 1. **子数组之和** 给定一个整数数组 `arr` 和多个查询 `[l, r]`,每次查询返回区间 `[l, r]` 的元素总和。 可以通过构建前缀和数组来解决此问题。定义 `dp[i]` 表示从索引 `0` 到 `i` 的累加和,则任意区间的和可以表示为 `dp[r] - dp[l-1]`(当 `l>0`)。这种方法的时间复杂度为 O(n),单次查询则只需 O(1)[^4]。 ```python def build_prefix_sum(arr): n = len(arr) prefix_sum = [0] * (n + 1) for i in range(1, n + 1): prefix_sum[i] = prefix_sum[i - 1] + arr[i - 1] return prefix_sum def query(prefix_sum, l, r): return prefix_sum[r + 1] - prefix_sum[l] # Example Usage arr = [1, 2, 3, 4, 5] prefix_sum = build_prefix_sum(arr) print(query(prefix_sum, 1, 3)) # Output: 9 ``` --- #### 2. **连续数组的最大长度** 找到最长的连续子数组,其中 `0` 和 `1` 的数量相等。 通过将 `0` 转化为 `-1` 并利用前缀和的思想,我们可以记录每个前缀和首次出现的位置。如果两个不同的位置具有相同的前缀和,则它们之间的子数组满足条件[^2]。 ```cpp class Solution { public: int findMaxLength(vector<int>& nums) { unordered_map<int, int> hash; hash[0] = -1; // 默认有一个前缀和为0的情况 int sum = 0, ret = 0; for(int i = 0; i < nums.size(); ++i){ sum += (nums[i] == 0 ? -1 : 1); // 计算当前位置的前缀和 if(hash.count(sum)){ ret = max(ret, i - hash[sum]); } else{ hash[sum] = i; } } return ret; } }; ``` --- #### 3. **子数组被 K 整除的数量** 找出能被 `k` 整除的子数组数目。 对于这个问题,我们需要考虑同余性质并结合哈希表存储前缀和模 `k` 后的结果。具体来说,若两处前缀和对 `k` 取模相同,则这两者之间形成的子数组必然能够被 `k` 整除[^1]。 ```cpp class Solution { public: int subarraysDivByK(vector<int>& nums, int k) { unordered_map<int, int> hash; hash[0] = 1; // 初始化:前缀和为0的情况计一次 int sum = 0, ret = 0; for(auto x : nums){ sum += x; int r = ((sum % k) + k) % k; // 处理负数情况下的取模运算 if(hash.count(r)){ ret += hash[r]; } hash[r]++; } return ret; } }; ``` --- #### 4. **矩阵区域和** 给定二维矩阵 `matrix` 和若干个矩形区域 `(row1, col1)` 至 `(row2, col2)`,求这些区域内所有元素的和。 扩展一维前缀和至二维场景即可完成任务。先按照行方向建立每一列上的累积值,再基于此进一步计算整个矩形范围内的数值总和[^3]。 ```python def matrix_region_sum(matrix, row1, col1, row2, col2): m, n = len(matrix), len(matrix[0]) # 构建二维前缀和 prefix_sum = [[0]*(n+1) for _ in range(m+1)] for i in range(1,m+1): for j in range(1,n+1): prefix_sum[i][j] = matrix[i-1][j-1] \ + prefix_sum[i-1][j] \ + prefix_sum[i][j-1] \ - prefix_sum[i-1][j-1] # 查询指定区域的和 result = prefix_sum[row2+1][col2+1] \ - prefix_sum[row1][col2+1] \ - prefix_sum[row2+1][col1] \ + prefix_sum[row1][col1] return result ``` --- #### 5. **奇数长度子数组的和** 给出一个正整数列表,请求出其所有可能组成的奇数长度子数组各自元素之和的总计。 借助前缀和技巧以及适当调整遍历逻辑,可以在较短时间内得出答案。 ```cpp int sumOddLengthSubarrays(vector<int>& arr) { int totalSum = 0; int length = arr.size(); vector<int> prefix(length + 1); for(int i = 1; i <= length; ++i){ prefix[i] = prefix[i - 1] + arr[i - 1]; } for(int size = 1; size <= length; size += 2){ // 奇数大小 for(int start = 0; start + size <= length; ++start){ int end = start + size - 1; totalSum += prefix[end + 1] - prefix[start]; } } return totalSum; } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值