“21天好习惯”第一期-1 前缀和

21天零基础入门ACM

21天零基础入门ACM之 第1天

前缀和

什么是前缀和

前缀和,顾名思义,就是把前缀加起来。

加上给定一个数组a[] = {1,2,3,4,5},那么思考一下,它的前缀有哪些

{1},{1,2},{1,2,3},{1,2,3,4},{1,2,3,4,5}

前缀和就是他们前缀的和。

比如:

sum[0]=a[0];

sum[1]=a[0]+a[1];

sum[2]=a[0]+a[1]+a[2]

sum[3]=a[0]+a[1]+a[2]+a[3]

sum[4]=a[0]+a[1]+a[2]+a[3]+a[4]

sum数组就是a的前缀和数组

在这里插入图片描述

前缀和的作用

首先思考一下给出一个区间[l,r],如果我要计算 lr 区间内所有元素的和,怎么做?

  1. 方法一:从区间 lr 做一次循环,然后计数,时间复杂度位O(n);
  2. 方法二:利用前缀和,sum[r]-sum[l-1] 的值,即为区间 lr的数字和的值,时间复杂度位O(1)

前缀和的应用

例题1:https://ac.nowcoder.com/acm/contest/11471/C
题目描述:
在这里插入图片描述
在这里插入图片描述

思路:妥妥的前缀和板子题,注意千万不要暴力模拟,时间复杂度为O(n*n),绝对超时。
代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 7;
int n, m;
ll nums[N];  
ll sum[N];  // 前缀和数组
int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        cin >> nums[i];
        sum[i] = sum[i - 1] + nums[i];
    }
    while (m--) {
        int l, r;
        cin >> l >> r;
        cout << sum[r] - sum[l - 1] << endl;  //利用前缀和快速输出区间和
    }
    return 0;
}

例题2:https://ac.nowcoder.com/acm/contest/19483/A
题目描述:
在这里插入图片描述
在这里插入图片描述
思路:还是前缀和,只不过sum数组存的是前缀积,求[l,r]的积的时候,只需要sum[r]/sum[l-1] 即可,但是此题要用上逆元,有兴趣的小伙伴可以去看看逆元。
代码:

#include <bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
ll qpow(ll a, ll b) { ll ans = 1;    while (b) { if (b & 1)    ans *= a;        b >>= 1;        a *= a; }    return ans; }    
ll qpow(ll a, ll b, ll mod) { ll ans = 1;  a%=mod; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; }
const int mod=1e9+7;
const int N=1e5+7;

ll n, m, a[N];
int x, y;
int main() {
    a[0] = 1;
    while (cin >> n >> m) {
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        for (int i = 2; i <= n; i++) {
            a[i] = (a[i - 1] * a[i]) % mod;
        }
        while (m--) {
            cin >> x >> y;
            cout << (qpow(a[x - 1], mod - 2, mod) * a[y]) % mod << endl; 
            // 逆元求出a[y] / a[x-1]  的积
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值