P5686 [CSP-S2019 江西] 和积和

题意

给定两个下标从 \(1\)\(n\) 编号的序列 \(a_i,b_i\),定义函数,

\(S(l,r)(1 \leq l\leq r \leq n)\)\(\sum_{i=l}^{r}a_i \times \sum_{i=l}^{r}b_i\)

要求出下列式子的值:\(\sum_{l=1}^{n}\sum_{r=1}^{n}S(l,r)\)

将答案模 \(1e9+7\)

分析

\(sa_i = \sum_{j=1}^{i}{a_i}\)\(sb_i = \sum_{j=1}^{i}{b_i}\),$ suma_i= \sum_{j=1}^{i}{sa_i}$ , \(sumb_i= \sum_{j=1}^{i}{sb_i}\)
\(sum_i=\sum_{j=1}^{i}{a_j \times b_j}\)

对于每一个 \(r\)

  • \(res_r=\sum_{l=1}^{r}{(sa_r -sa_l)\times (sb_r -sb_l)}\)
  • $res_r=\sum_{l=1}^{r}{sa_r \times sb_r - sa_{l-1}\times sb_r - sa_r}\times sb_{l-1}+sb_{l-1}\times sa_{l-1} $。
  • \(res_r=r\times sa_r \times sb_r -sb_r\times suma_{r-1}\times -sa_r\times sumb_{r-1}+sum_{r-1}\)

最后 \(ans=\sum_{i=1}^{n}{res_i}\)

记得变乘边模,特别是 \(i\times sa_i\times sb_i\) 容易炸 int。

#include<bits/stdc++.h>
#define mod 1000000007
#define N 500005
#define int long long
using namespace std;
int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int n,ans;
int a[N],b[N],suma[N],sumb[N],sum[N];
signed main(){
	n=read();
	for(int i=1;i<=n;++i) a[i]=(read()+a[i-1])%mod;
	for(int i=1;i<=n;++i) b[i]=(read()+b[i-1])%mod;
	for(int i=1;i<=n;++i) suma[i]=(suma[i-1]+a[i])%mod;
	for(int i=1;i<=n;++i) sumb[i]=(sumb[i-1]+b[i])%mod;
	for(int i=1;i<=n;++i) sum[i]=(sum[i-1]+a[i]*b[i])%mod;
	for(int i=1;i<=n;++i)
		ans=(ans+(i*a[i]%mod*b[i]%mod+sum[i-1]%mod-((b[i]*suma[i-1]%mod+a[i]*sumb[i-1]%mod)%mod)+mod)%mod)%mod;
	printf("%d\n",ans);
	return 0;
}
posted @ 2022-11-01 20:41  Aurora-JC  阅读(66)  评论(0编辑  收藏  举报