对于这种式子 一般情况下,我们先仿照答案写出前几项,看看有没有规律
定义前缀和 ,把要求出的式子
展开来写
然后,通过观察发现,可以把每一个列 相加的值,合并到一起
建议列成一排这样约分一眼就看出来了,每次都是前面空出几项,后面空出几项
通过观察式子,我们发现
对应
加一项
减去
项
对应
加两项
减去
项
对应
加三项
减去
项
而且这些加的,或者减去的,都是一段区间的数字,也可以用前缀和来优化
定义前缀和 ,改写原先的式子,即
得到通式
然后我们就可以应用两遍前缀和 求出答案了
最终式子 ,记得每步都取模
有个细节, 数组要用
不然在求前缀和的时候会爆掉,因为
已经是临界值了,
和
两个相加会先爆掉再取模
#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;
} 
京公网安备 11010502036488号