最新文章

这里会显示最新的几篇文章摘要。

鲁的学生(模拟)


问题 A: 鲁的学生

时间限制: 1.000

题目描述

在宇宙大帝 Luke 的星球 Lu3KO5 上,有一所著名的星际学院,专门培养年轻的星际探险家们。在这一天,Luke 亲自担任数学导师,为这些年轻学员们组织了一场有趣的课堂活动。

Luke 让他的学生们站成一排,一共有 n 位学员。每位学员将随意选择一个代表他们能力值的数字 A[i]。接着,Luke 提出了一项挑战:在这些学员中,可以任意选择两名学员,并将他们之间的所有学员作为一个小组(包括这两名学员)。小组中的每个人所拿到的数字之和被称为该小组的“总分数”。

现在,Luke 想知道,如果将所有可能的小组都计算一遍,他们的“总分数之和”会是多少。由于结果可能非常庞大,请你帮助他计算这个结果对 1000000007 取模后的值。

输入

第一行输入一个非负整数 n

第二行输入 n 个非负整数,表示 A[i]

输出

输出一个整数,即答案

样例输入

3
1 2 3

样例输出

20

提示

样例解释:
若选择1则和为1。
若选择[1,2]则和为1+2=3。
若选择[1,3]则和为1+2+3=6。
若选择[2,2]则和为2。
若选择[2,3]则和为2+3=5。
若选择[3,3]则和为3。

对于前 30% 的数据 \(1≤n≤100\)
对于前 60% 的数据 \(1≤n≤1000\)
对于 100% 的数据 \(1≤n≤10^7, 0≤A[i]≤50000\)

分析

模拟答案可以得到,设第i个数为\(a_i\)

  1. 当长度为一的区间,每个数被和加入一次,
  2. 长度为2,除了\(a_1\)\(a_n\),其余的数字都被加入两次(滑动)
  3. 长度为3的时候,除了\(a_1\)\(a_n\)被加入一次,\(a_2\)\(a_n_1\)被加入两次,其余的数字都被加入三次
  4. 虑下标为 i 的数字 a[i]。在所有连续区间中,要保证 a[i] 被包含,区间的左端点必须在 1 到 i 之间,右端点必须在 i 到 n 之间。
    左端点有 i 种选法,右端点有 (n-i+1) 种选法,因此 a[i] 出现在的连续区间总数为
      \(i × (n-i+1)\)
  5. 最终所有区间的总和即为每个数字 a[i] 乘以它出现的次数,再求和:
      答案 = \(Σ (a[i] × i × (n-i+1))  (i 从 1 到 n)\)

代码


#include <iostream>
#include<queue>
#include<vector>
#include<bitset>
#include<cstring>
#include<unordered_map>
#define de(x) cout << (#x) << "=" << x << '\n';
using namespace std;
#define int long long
const int N = 1e7 + 5,M = 1e9+7;
int v[N];
// //快读: 注意这里是引用符号,就相当与对要赋值的变量进行操作
// inline void read(int &x){
//     x = 0; int f = 1; char ch = getchar();
//     while(ch < '0' || ch > '9'){
//         if(ch == '-') f = -1;
//         ch = getchar();
//     }
//     while(ch >= '0' && ch <= '9')  x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
//     x = x * f; 
// }
signed main() {


    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    int n;
    cin >> n;
    int sum = 0;
    for(int i = 1;i <= n;++i){
        cin >> v[i];
        int t = min(i,n-i+1);
        int cn = t*n-t*(t-1);//de(cn);
        sum = v[i] * cn % M + sum;
    }

    cout << sum%M;


}
posted @ 2025-03-23 15:14  bakul  阅读(123)  评论(0)    收藏  举报