牛客国庆集训派对Day4G-区间权值

牛客国庆集训派对Day4G-区间权值
题解:
ans=ans=
f(1,1)+f(1,2)+...+f(1,n)+f(1,1)+f(1,2)+...+f(1,n)+
f(2,2)+f(2,3)+...+f(2,n)+f(2,2)+f(2,3)+...+f(2,n)+
......
f(n1,n1)+f(n1,n)+f(n-1,n-1)+f(n-1,n)+
f(n,n)f(n,n)
s[i]=a[1]+a[2]+...+a[i]s[i]=a[1]+a[2]+...+a[i]
ans=ans=
s[1]w1+s[2]w2+s[3]w3+...+s[n]wn+s[1]w_1+s[2]w_2+s[3]w_3+...+s[n]w_n+
(s[2]s[1])w1+(s[3]s[1])w2+...+(s[n]s[1])wn1+(s[2]-s[1])w_1+(s[3]-s[1])w_2+...+(s[n]-s[1])w_{n-1}+
(s[3]s[2])w1+(s[4]s[2])w2+...+(s[n]s[2])wn2+(s[3]-s[2])w_1+(s[4]-s[2])w_2+...+(s[n]-s[2])w_{n-2}+
......
(s[n1]s[n2])w1+(s[n]s[n2])w2+(s[n-1]-s[n-2])w_1+(s[n]-s[n-2])w_2+
(s[n]s[n1])w1(s[n]-s[n-1])w_1
这时将每一列相加,可得
s[n]w1+s[n]w_1+
(s[n]+s[n1]s[1])w2+(s[n]+s[n-1]-s[1])w_2+
(s[n]+s[n1]+s[n2]s[2]s[1])w3(s[n]+s[n-1]+s[n-2]-s[2]-s[1])w_3
......
s[n]wns[n]w_n
这时就又需要一重前缀和了。
S[i]=s[1]+s[2]+...+s[i]S[i]=s[1]+s[2]+...+s[i]
最终ans=i=1n(S[n]S[ni]S[i1])wians=\sum_{i=1}^{n}(S[n]-S[n-i]-S[i-1])wi
CodeCode:

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7,N=3e5+5;
int s[N],a[N],w[N],n;
long long S[N];
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		s[i]=(s[i-1]+a[i])%mod;
	}
	for(int i=1;i<=n;i++)scanf("%d",&w[i]);
	for(int i=1;i<=n;i++)
		S[i]=(S[i-1]+s[i])%mod;
	long long ans=0;
	for(int i=1;i<=n;i++)
		ans=(ans+((S[n]-S[n-i]-S[i-1]+mod)%mod*w[i]%mod)%mod)%mod;
	printf("%lld\n",ans);
	return 0;
}