牛客国庆集训派对Day4 区间权值

区间权值

https://ac.nowcoder.com/acm/problem/19798

对于这种式子 一般情况下,我们先仿照答案写出前几项,看看有没有规律

定义前缀和 ,把要求出的式子展开来写
然后,通过观察发现,可以把每一个列 相加的值,合并到一起

建议列成一排这样约分一眼就看出来了,每次都是前面空出几项,后面空出几项
通过观察式子,我们发现

对应 加一项 减去

对应 加两项 减去

对应 加三项 减去

而且这些加的,或者减去的,都是一段区间的数字,也可以用前缀和来优化

定义前缀和 ,改写原先的式子,即

得到通式

然后我们就可以应用两遍前缀和 求出答案了

最终式子 ,记得每步都取模

有个细节, 数组要用 不然在求前缀和的时候会爆掉,因为 已经是临界值了, 两个相加会先爆掉再取模

#include <bits/stdc++.h>
using namespace std;
#define endl '\n' 
#define IO ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
typedef long long LL;
const int N = 3e5 + 5;
const int mod = 1e9 + 7;
int a[N],w[N],s[N],n;
LL E[N];
int main() {
#ifndef ONLINE_JUDGE
    freopen("D:/scode/in.txt","r",stdin);
    //freopen("D:/scode/out.txt","w",stdout);
#endif
    IO;
    cin >> n;
    for(int i = 1;i <= n; ++i) cin >> a[i];
    for(int i = 1;i <= n; ++i) cin >> w[i];
    // 先对ai 求一遍前缀和
    for(int i = 1;i <= n; ++i) s[i] = (s[i - 1] + a[i]) % mod;
    // 再对si 求一遍前缀和
    for(int i = 1;i <= n; ++i) E[i] = (E[i - 1] + s[i]) % mod;
    // 计算答案
    int ans = 0;
    for(int i = 1;i <= n; ++i) 
        ans = (ans + ((E[n] - E[n - i] - E[i - 1] + mod) % mod * w[i]) % mod) % mod;
    cout << ans << endl;
    return 0;
}
全部评论

相关推荐

06-12 16:00
天津大学 Java
牛客30236098...:腾讯坏事做尽,终面挂是最破防的 上次被挂了后我连简历都不刷了
点赞 评论 收藏
分享
小鹏、大疆、米哈游、MinMax小鹏上午投的下午就约面,进度未免也太快了
蛇年行大运fff:哥们 盗贴有意思吗,我发xhs上的给你搬过来了😅😅😅
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务