1 条题解

  • 0
    @ 2026-10-19 0:36:27

    [CSP-S 2019 江西] 和积和

    知识点

    区间贡献、前缀和、递推计数

    解题思路

    处理第r项前,令A、B分别为所有以r-1结尾区间的a和、b和之总和,C为这些区间两种和乘积的总和。追加ar、br时,每个旧区间乘积增加ar·旧b和+br·旧a和+ar·br,另有单点区间ar·br,因此C更新为C+ar·B+br·A+r·ar·br。随后A加r·ar、B加r·br,把新C加入答案。所有运算随时取模。

    正确性说明

    以r结尾的区间由以r-1结尾的每个区间追加新项,加上单点[r,r]构成,恰有r个。展开每个区间的乘积并求和,得到C的递推。A、B同理各追加r次新值。由归纳法状态正确,而每个区间按右端点恰被计入一次,最终累加正确。

    易错点

    计算C要使用更新前的A、B;r·ar·br分步取模,不能直接做三个大数的乘积;使用64位。

    复杂度

    时间O(n),此实现为保存输入a使用O(n)空间,递推状态O(1)。

    参考代码(GNU C++17)

    #include<bits/stdc++.h>
    using namespace std;
    int main(){ios::sync_with_stdio(false);cin.tie(nullptr);const long long P=1000000007;int n;cin>>n;vector<long long>a(n+1);for(int i=1;i<=n;i++)cin>>a[i];long long A=0,B=0,C=0,ans=0;for(long long i=1;i<=n;i++){long long b;cin>>b;C=(C+a[i]*B%P+b*A%P+i*a[i]%P*b%P)%P;A=(A+i*a[i])%P;B=(B+i*b)%P;ans=(ans+C)%P;}cout<<ans<<'\n';}
    
    • 1

    信息

    ID
    869
    时间
    1000ms
    内存
    125MiB
    难度
    普及+
    标签
    递交数
    0
    已通过
    0
    上传者