题目链接
题目描述
小红定义一个长度为 的数组的权值为
。现在小红有一个长度为
的数组,她想知道所有子数组的权值和是多少?答案对
取模。
输入:
- 第一行输入一个整数
。
- 第二行输入
个整数。
输出:
- 输出一个非负整数,表示答案对
取模的结果。
解题思路
这道题目的关键是理解数组权值的定义和所有子数组的概念。
-
一个长度为
的数组的权值被定义为
,即每个元素乘以它在数组中的位置(从
开始计数)后的总和。
-
为了高效解决这个问题,我们需要数学推导来避免暴力枚举所有子数组。
-
考虑原数组中位置
的元素
(下标从
开始)对最终结果的贡献:
- 对于任何包含
的子数组
(其中
),
在这个子数组中的位置是
。
- 子数组的起点
可以是
到
,共
种可能。
- 子数组的终点
可以是
到
,共
种可能。
- 对于任何包含
-
因此,
在所有子数组中的权值贡献为:
-
简化这个表达式:
-
因此,
的总贡献为:
-
对所有元素的贡献求和,得到最终结果。
代码
#include <iostream>
#include <vector>
using namespace std;
const int MOD = 1e9 + 7;
int main() {
int n;
cin >> n;
vector<int> arr(n);
for (int i = 0; i < n; ++i) {
cin >> arr[i];
}
long long result = 0;
// 遍历每个元素,计算其在所有子数组中的贡献
for (int i = 0; i < n; ++i) {
// 计算 i 在 0-indexed 下的贡献
long long position_sum = (long long)(i + 1) * (i + 2) / 2;
long long subarrays = (long long)(n - i);
long long contribution = (position_sum * subarrays) % MOD;
// 将当前元素对最终结果的贡献加入
result = (result + ((long long)arr[i] * contribution) % MOD) % MOD;
}
cout << result << endl;
return 0;
}
import java.util.Scanner;
public class Main {
private static final int MOD = (int)(1e9 + 7);
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}
long result = 0;
// 遍历每个元素,计算其在所有子数组中的贡献
for (int i = 0; i < n; i++) {
// 计算 i 在 0-indexed 下的贡献
long positionSum = (long)(i + 1) * (i + 2) / 2;
long subarrays = (long)(n - i);
long contribution = (positionSum * subarrays) % MOD;
// 将当前元素对最终结果的贡献加入
result = (result + ((long)arr[i] * contribution) % MOD) % MOD;
}
System.out.println(result);
}
}
def solve(arr, n):
MOD = 10**9 + 7
result = 0
# 遍历每个元素,计算其在所有子数组中的贡献
for i in range(n):
# 计算 i 在 0-indexed 下的贡献
position_sum = (i + 1) * (i + 2) // 2
subarrays = n - i
contribution = (position_sum * subarrays) % MOD
# 将当前元素对最终结果的贡献加入
result = (result + (arr[i] * contribution) % MOD) % MOD
return result
n = int(input())
arr = list(map(int, input().split()))
print(solve(arr, n))
算法及复杂度
- 算法:数学推导 + 线性遍历。
- 时间复杂度:
,其中
是数组长度。我们只需要遍历数组一次,对每个元素计算其贡献。
- 空间复杂度:
,用于存储输入数组。
由于时间限制为 秒,空间限制为
MB,而我们的算法时间复杂度为
,对于题目给定的约束条件(数组长度和元素大小)来说,这是一个高效的解法,完全可以在时限内完成计算。