牛客国庆集训派对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;
}
全部评论

相关推荐

不愿透露姓名的神秘牛友
07-10 14:10
啊啊啊啊好幸福,妈妈是我找工作发疯前的一束光
黑皮白袜臭脚体育生:看了这篇帖子之后已经第一百次质问老妈,仍然没有得到我的老妈是老板的回答
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

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