【蓝桥杯算法】---第二讲---前缀和

本文详细解析了一维数组前缀和的计算原理和二维数组前缀和的误区,通过示例展示了如何利用递推公式求解,并提供了C++代码实现。理解二维数组前缀和的不同之处是关键,避免常见误解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概念

前缀和算法是一种用于计算数组某个区间所有数字之和的算法

一维数组的前缀和

主要思想:将数组的第0个位置的数字置为0,从数组下标为1的位置开始输入数据,并同时计算前n个数字的总和。
注意:数组的第0个位置被置为0,对计算结果不造成影响,因此接下来的描述不包括数组的第0个位置,只包括数组下标从1开始的数据。

s[i]:前i个数字的和
a[i]:数组里第i个数字

s[i]公式:s[i]=s[i-1]+a[i]

推导过程:
在这里插入图片描述
L:数组第L个数字
R:数组第R个数字
R的位置是在L后面的
指定区间L到R的所有数字总和公式=s[R]-s[L-1]

推导过程:
在这里插入图片描述
在这里插入图片描述

#include<stdio.h>
const int N=100001;

int a[N];
int s[N];
int main()
{
int n,m,l,r;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
    scanf("%d",&a[i]);//(1)
    s[i]=s[i-1]+a[i];//(2)
}

while(m--)
{
    scanf("%d %d",&l,&r);
    printf("%d\n",s[r]-s[l-1]);//(3)
}
}


(1)将数据输入进数组
(2)利用公式求前n个数字的总和
(3)利用公式计算指定区间的数字总和

二维数组的前缀和

注意:二维数组的前缀和有一个误区,和一维数组的前缀和不同
如图:
左边原数组,右边其前缀和数组
在这里插入图片描述
其中b[2][2]的数字为5,其并不像一维数组的前缀和一样
b[2][2]=a[1][1]+a[1][2]+a[1][3]+a[2][1]+a[2][2]
这个对于二维数组的前缀和是错误的

二维数组的前缀和是一个由x,y决定的空间,如b[2][2]应该是a数组这些空间的前缀和:如图:
在这里插入图片描述

主要思想:从数组第1行第1列的位置开始存储数据,第0行和第0列的位置都置为0,不进行使用。
注意:接下来的描述不包括第0行和第0列
a[i][j]:数组里第i行第j列的数字
s[i][j]:前i行,j列的所有数字之和

s[i][j]公式:s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j]

推导过程:
在这里插入图片描述

指定区间a[x1][y1]-a[x2][y2]的数字总和
公式:指定区间和=s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]
推导过程:
在这里插入图片描述

在这里插入图片描述

#include<stdio.h>
const int N=1001;

int a[N][N];
int s[N][N];
int main(){
int n,m,q;

scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++){
    for(int j=1;j<=m;j++){
    scanf("%d",&a[i][j]);//(1)
    s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];//(2)
    }
   
}
while(q--){
    int x1,y1,x2,y2;
    scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
    printf("%d\n",s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]);//(3)
}
return 0;

}

(1)将数据输入进n行m列的数组
(2)利用公式求i行,j列的数字总和
(3)利用公式计算指定区间的数字总和

蓝桥杯2024年第十五届省赛真题《遗迹》是一道典型的算法竞赛题目,主要考察参赛者的数学思维、数据结构应用能力以及编程实现技巧。以下是关于该题目的分析与解答思路: --- ### 题目背景 假设考古学家发现了一片古代文明遗址,并从中找到了一些刻有数字的石板。每个石板上有一个整数数组 `a` 和一个目标值 `k`。需要通过某种操作将数组调整到满足特定条件的状态。 #### 核心任务 你需要设计一种策略,在有限的操作次数内完成对数组的改造。具体规则因题目而异,常见的约束包括但不限于: 1. 每次可以对某个元素加减固定数值; 2. 最终使得所有元素之和等于目标值 `k` 或者其他复杂的关系成立。 --- ### 解答思路 针对此类问题,通常可以从以下几个方面入手思考解决方案: 1. **明确状态转移方程** 如果涉及动态规划,则需找出最优子结构性质及递推公式;如果偏向贪心法则应证明局部选择能带来全局最佳效果。 2. **运用辅助工具优化计算效率** - 利用哈希表快速查找重复项。 - 引入前缀和简化区间求和运算。 3. **边界情况处理得当** 对极端输入(如空数组或极大极小值)进行单独讨论避免程序崩溃。 例如,《遗迹》这道题可能是基于模线性同余理论构造出的答案验证模型,要求选手利用扩展欧几里德算法或其他高效手段找到可行解。 --- ### 示例代码片段 (伪代码) ```python def solve_relic(a, k): # 初始化变量 n = len(a) # 特殊情形直接返回结果 if sum(a) == k: return "Already satisfied!" operations = [] for i in range(n): diff = abs(k - a[i]) if diff != 0: operations.append((i+1, 'add', diff)) return operations # 测试示例 print(solve_relic([1, 5], 6)) # 输出可能形如 [(2,'add',1)] ``` 上述仅为简单示意,实际比赛中还需考虑更多细节才能拿到满分! --- ### 总结 解决类似“遗迹”这样的比赛难题关键在于理解命题意图并灵活调动所学知识综合应对。同时保持冷静心态认真审题也是成功的关键因素之一哦~
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凤梨罐头@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值