P5686
原题:P5686 [CSP-S2019 江西] 和积和。
有异于其他题解的做法,我采用的是分治的方式来解决这道题目。
思路
所谓分治,就是对于所求区间
不过,我们需要在
在本题中,在
对于区间
根据初中数学乘法公式,
考虑对于两个区间:
考虑维护预处理
再考虑的就是枚举
最终,两侧
采用分治,时间复杂度
提示:要开 long long,别忘了处处取模。
代码
// author: syl
// language: c++
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e5+5, mod = 1e9+7;
int a[N],b[N],c[N];
int res=0;
void solve(int l,int r) {
if(l==r) { res=(res+c[l])%mod; return; }
int mid=l+r>>1,zca=0,zcb=0,sumal=0,sumbl=0;
for(int i=mid;i>=l;--i) {
zca=(zca+a[i])%mod;
sumal=(sumal+zca)%mod;
zcb=(zcb+b[i])%mod;
sumbl=(sumbl+zcb)%mod;
int lk=zca*zcb;
res=(res+((zca*zcb)%mod)*(r-mid))%mod;
} zca=0,zcb=0;
int sumar=0,sumbr=0;
for(int i=mid+1;i<=r;++i) {
zca=(zca+a[i])%mod;
sumar=(sumar+zca)%mod;
zcb=(zcb+b[i])%mod;
sumbr=(sumbr+zcb)%mod;
res=(res+((zca*zcb)%mod)*(mid-l+1))%mod;
} res=(res+sumal*sumbr+sumar*sumbl)%mod;
solve(l,mid),solve(mid+1,r);
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr),
cout.tie(nullptr);
int n; cin>>n;
for(int i=1;i<=n;++i) cin>>a[i];
for(int i=1;i<=n;++i) cin>>b[i];
for(int i=1;i<=n;++i) c[i]=(a[i]*b[i])%mod;
solve(1,n);
cout<<res%mod<<'\n';
return 0;
}
我的 AC 记录。