对于这种式子 一般情况下,我们先仿照答案写出前几项,看看有没有规律

定义前缀和 ,把要求出的式子展开来写
然后,通过观察发现,可以把每一个列 相加的值,合并到一起

建议列成一排这样约分一眼就看出来了,每次都是前面空出几项,后面空出几项
通过观察式子,我们发现

对应 加一项 减去

对应 加两项 减去

对应 加三项 减去

而且这些加的,或者减去的,都是一段区间的数字,也可以用前缀和来优化

定义前缀和 ,改写原先的式子,即

得到通式

然后我们就可以应用两遍前缀和 求出答案了

最终式子 ,记得每步都取模

有个细节, 数组要用 不然在求前缀和的时候会爆掉,因为 已经是临界值了, 两个相加会先爆掉再取模

#include <bits/stdc++.h>
using namespace std;
#define endl '\n' 
#define IO ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
typedef long long LL;
const int N = 3e5 + 5;
const int mod = 1e9 + 7;
int a[N],w[N],s[N],n;
LL E[N];
int main() {
#ifndef ONLINE_JUDGE
    freopen("D:/scode/in.txt","r",stdin);
    //freopen("D:/scode/out.txt","w",stdout);
#endif
    IO;
    cin >> n;
    for(int i = 1;i <= n; ++i) cin >> a[i];
    for(int i = 1;i <= n; ++i) cin >> w[i];
    // 先对ai 求一遍前缀和
    for(int i = 1;i <= n; ++i) s[i] = (s[i - 1] + a[i]) % mod;
    // 再对si 求一遍前缀和
    for(int i = 1;i <= n; ++i) E[i] = (E[i - 1] + s[i]) % mod;
    // 计算答案
    int ans = 0;
    for(int i = 1;i <= n; ++i) 
        ans = (ans + ((E[n] - E[n - i] - E[i - 1] + mod) % mod * w[i]) % mod) % mod;
    cout << ans << endl;
    return 0;
}