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;
}

浙公网安备 33010602011771号