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