和积和

和积和

这道题侧重于考察数学功底

首先,前缀和优化一般都是能想到的,但是这样的复杂度是 \(O(n^2)\)

考虑对于小的情况进行模拟。

\(sa_i\) 表示 \(\sum_{i=1}^n a_i\)\(sb_i\) 同理。

\(S(1,1)=sa_1*sb_1\)

\(S(1,2)=sa_2*sb_2\)

\(S(1,3)=sa_3*sb_3\)

\(S(2,2)=(sa_2-sa_1)(sb_2-sb_1)=sa_2*sb_2-sa_2*sb_1-sa_1*sb_2+sa_1*sb_1\)

\(S(2,3)=(sa_3-sa_1)(sb_3-sb_1)=sa_3*sb_3-sa_3*sb_1-sa_1*sb_3+sa_1*sb_1\)

\(S(3,3)=(sa_3-sa_2)(sb_3-sb_2)=sa_3*sb_3-sa_2*sb_3-sa_3*sb_2+sa_2*sb_2\)

作和,将右边 \(+3\sum_{i=1}^3sa_isb_i\),再减掉。

将符号为正的部分和符号为负的部分分别计算

正的:\(+4\sum_{i=1}^3sa_isb_i\)(其实加一项对于左边只是修改了一下系数)。

负的:通过因式分解得 \(-(sa_1+sa_2+sa_3)(sb_1+sb_2+sb_3)\)(重点是补全 \(sa_isb_i\) 这样的项方便因式分解)。

显然,对于每个 \(n\) 都有:

要求的 \(=\) \((n+1)\sum_{i=1}^nsa_isb_i-\sum_{i=1}^nsa_i\sum_{i=1}^nsb_i\)

显然,前缀和 \(O(1)\) 查询和 \(O(n)\) 枚举。

#include<cstdio>
using namespace std;
#define de(N,x) const int N=x
#define Ls(i,l,r) for(int i=l;i<r;++i)
#define Rs(i,l,r) for(int i=r;i>l;--i)
#define L(i,l) for(int i=1;i<=l;++i)
de(N,500010);
de(mod,1e9+7);
typedef long long ll;
ll a[N],b[N],suma,sumb,ans;
int n;
int main(){
    // freopen("1.in","r",stdin);
    // freopen("1.out","w",stdout);
    // ios::sync_with_stdio(0);
    // cin.tie(0);
    // cout.tie(0);
    scanf("%d",&n);
    L(i, n)scanf("%lld",a+i),(a[i]+=a[i-1])%=mod;
    L(i, n)scanf("%lld",b+i),(b[i]+=b[i-1])%=mod;
    L(i, n){
        (ans+=a[i]*b[i]%mod)%=mod;
        (suma+=a[i])%=mod;
        (sumb+=b[i])%=mod;
    }
    (ans*=n+1)%=mod;
    (ans+=mod-suma*sumb%mod)%=mod;
    printf("%lld",ans);
    return 0;
}
posted @ 2023-05-24 13:19  wscqwq  阅读(9)  评论(0编辑  收藏  举报