[Luogu5686] 和积和

Description

给定两个下标从\(1\)\(n\)编号的序列 \(a_i,b_i\),定义函数\(S(l,r)(1\le l\le r\le n)\)为:

\[\sum_{i=l}^r a_i\times \sum_{i=l}^r b_i\]

请你求出下列式子的值:

\[\sum_{l=1}^n \sum_{r=l}^n S(l,r)\]

由于答案可能很大,你只需要给出答案模 \(10^9+7\)后的结果。

Input

第一行一个正整数\(n\)表示序列长度。

第二行\(n\)个正整数表示\(a_i\)

第三行\(n\)个正整数表示\(b_i\)

Output

仅一行一个整数表示答案模\(10^9+7\)后的结果。

Sample Input1

3
2 3 4
3 4 5

Sample Output1

244

Sample Input2

5
11 22 33 44 55
12 34 56 78 90

Sample Output2

201542

Hint

对于\(20\%\)的数据:\(n\le 10\) , \(a_i,b_i\le 10\)

对于\(40\%\)的数据:\(n\le 200\) , \(a_i,b_i\le 100\)

对于\(70\%\)的数据:\(n\le 3000\) , \(a_i,b_i\le 10^5\)

对于\(100\%\)的数据:\(3\le n\le 5\times 10^5\) , \(1\le a_i,b_i\le 10^9\)

题解


\(PS\):我们机房里的\(OIer\)几乎都做出来了,下面分别给出一下几个人的理解


AC黑洞

考虑第\(i\)列的\(a_i\)\(b_i\),它可以与第\(j(1\le j\le i-1)\)列的到第\(i\)列组成一个\(S(l,r)\),我们用\(sa\)记录前\(i-1\)\(a\)将与\(b_i\)乘多少次,用\(sb\)记录前\(i-1\)\(b\)将与\(a_i\)乘多少次,\(f_i\)记录\(\sum_{j=1}^i S(j,i)\),答案就是\(\sum_{i=1}^n f_i\)

#include<iostream>
#include<cstdio>
using namespace std;

typedef long long ll;
const ll MOD=(1e+9)+7;
const int N=(5e+5)+1;
ll a[N],b[N],sa,sb,f,Ans;

void Scanf(ll &num)
{
    int n=0; char c=getchar();
    while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') n=(n<<3)+(n<<1)+(c^48),c=getchar();
    num=n;
}

int main()
{
    int n;
    scanf("%d",&n);
    for(register int i=1;i<=n;++i) Scanf(a[i]);
    for(register int i=1;i<=n;++i) Scanf(b[i]);
    for(register int i=1;i<=n;++i)
    {
        f=(f+sa*b[i]+sb*a[i]+(i*a[i])%MOD*b[i])%MOD,
        sa=(sa+i*a[i])%MOD,
        sb=(sb+i*b[i])%MOD,
        Ans=(Ans+f)%MOD;
    }
    cout<<Ans<<endl;
    return 0;
}

lxyzxzy

  • T2终于写出来啦!

\(70~pts\)前缀和

#include<iostream>
#include<cstdio>
using namespace std;
const int inf=1e9+7;
const int N=5e5+5;
int a[N],b[N];long long suma[N],sumb[N];
int main()
{
    int n;long long ans=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),suma[i]=(suma[i-1]+a[i])%inf;
    for(int i=1;i<=n;i++) scanf("%d",&b[i]),sumb[i]=(sumb[i-1]+b[i])%inf;
    for(int i=1;i<=n;i++)
        for(int j=i;j<=n;j++) ans=(ans+(suma[j]-suma[i-1])*(sumb[j]-sumb[i-1]))%inf;
    cout<<ans<<endl;
    return 0;
}

\(100~pts\)

#include<iostream>
#include<cstdio>
using namespace std;
const int inf=1e9+7;
long long a[500005],b;
inline int read()
{ 
int s=0;
char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s; 
}
int main()
{
    int n;long long ans=0,suma=0,sumb=0,t=0;
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    for(int i=1;i<=n;i++)
    {
        b=read();
        t=(t+(((suma*b)%inf)+(sumb*a[i])%inf)%inf)%inf;
        t=(t+((a[i]*=i)%inf*b)%inf)%inf;
        suma=(suma+a[i])%inf;
        sumb=(sumb+i*b)%inf;
        ans=(ans+t)%inf;
    }
    cout<<ans<<endl;
    return 0;
}

YangChuYun

#include<bits/stdc++.h>
using namespace std;
const int INF=1e9+7,MAX=5e+6;
typedef long long LL;
LL a[MAX],b,sum1[MAX],sum2[MAX];
LL n,ans=0;
int main()
{
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
    }
    for(int i=1,j=n;i<=n;i++,j--)
    {
        scanf("%lld",&b);
        sum1[i]=sum1[i-1]+b*j;
        if(sum1[i]>15000000000000)sum1[i]%=INF;
        sum2[i]=sum2[i-1]+b*i;
        if(sum2[i]>15000000000000)sum2[i]%=INF;
    }
    for(int i=1,j=n;i<=n;i++,j--)
    {
        ans=(ans+(a[i]*((sum1[n]-sum1[i-1])*i%INF+sum2[i-1]*j%INF)))%INF;
    }
    printf("%lld",ans);
    return 0;
}

龙卷风

#include <iostream>
#include <cstdio>
using namespace std;
int Mod=1000000007;
long long ans=0,n,a[500001],b[500001];
inline int ReadIn(void)
{
    int sum = 0;
    int sign = 1;
    char ch = getchar();
    while(ch > '9' || ch < '0')
    {
        if(ch == '-')
        {
            sign = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        sum = sum*10+ch-'0';
        ch = getchar();
    }
    return sum*sign;
}
int main()
{
    n=ReadIn();
    for(int i=1;i<=n;i++)
    a[i]=ReadIn();
    long long d=0,c=0,e=0;
    for(int i=1;i<=n;i++)
    {
        b[i]=ReadIn();
        d=(d+(n-i+1)*b[i])%Mod;
    }
    for(int i=1;i<=n;i++)
    {
        ans=(ans+a[i]*((d-e)*i%Mod+c*(n-i+1)%Mod)%Mod)%Mod;
        c=(c+i*b[i])%Mod;
        e=(e+(n-i+1)*b[i])%Mod;
    }
    printf("%d",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/hihocoder/p/11963255.html