Solution
考虑每个数 (a_i) 对答案的贡献:若 (b) 中存在一个区间 ([l,r]) ((l leq i leq r)),则该区间的和 (sum_{l,r}) 必定会与 (a_i) 相乘恰好一次,并对答案产生相应的贡献。
现在问题转化为:对于每个下标 (i),求出 (b) 中所有包含该下标的区间的 (mathrm{sum}) 和(记为 (S_i))
例如样例一,(b) 中所有包含下标 (2) 的区间为 ([1,2]),([1,3]),([2,2]),([2,3]),它们的 (mathrm{sum}) 值依次为 (3+4=7),(3+4+5=12),(4=4),(4+5=9). (S_2=7+12+4+9=32). 所以 (a_2) 对答案产生的贡献为 (32*3=96).
尝试用 (mathrm{O(n)}) 的时间复杂度求出每个下标 (i) 的 (S) 值。设 (f_i) 为 (b) 中以 (i) 为左端点的区间的 (mathrm{sum}) 和,(g_i) 为 (b) 中以 (i) 为右端点的区间的 (mathrm{sum}) 和。得到递推式:
(f_i=f_{i+1}+b_i imes (n-i+1))
(g_i=g_{i-1}+b_i imes i)
设位置 (i) 的 (S) 值为 (S_i),有: (S_i=S_{i-1}+f_i-g_{i-1}). 其中 (g_{i-1}) 表示两端都在 (i) 左边的多余区间。
(ans=sum_{i=1}^n) (S_i imes a_i). 总复杂度 (mathrm{O(n)}).
Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 2333333, mod = 1000000007;
long long n, ans = 0, g[N], f[N], S[N], a[N], b[N];
int main()
{
scanf("%lld", &n);
g[0] = S[0] = f[n + 1] = 0;
for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
for(int i = 1; i <= n; i++) scanf("%lld", &b[i]);
for(int i = n; i >= 1; i--)
f[i] = (f[i + 1] % mod + (b[i] * (n - i + 1)) % mod) % mod;
for(int i = 1; i <= n; i++)
g[i] = (g[i - 1] % mod + (b[i] * i) % mod) % mod;
for(int i = 1; i <= n; i++)
{
S[i] = (S[i - 1] + f[i] - g[i - 1] + mod) % mod;
ans = (ans + (a[i] * S[i]) % mod) % mod;
}
printf("%lld", ans);
return 0;
}