当前位置: 首页 > news >正文

前缀和c++

目录

什么是前缀和?

如何计算前缀和?

前缀和有什么用?

实战

什么是前缀和?

前缀和可以将数组中的连续元素相加

sum是数组中第一个元素到第i个元素的和

感觉像是简单的dp?

如何计算前缀和?

很简单,只要遍历一遍数组,每次将a中当前元素加到上一个前缀和上

时间复杂度是O(N)

代码:

#include <iostream>
#include <vector>
using namespace std;
int main() {
    //原数组
    vector<int> a = { 1, 2, 3, 4, 5 };
    //前缀和数组
    vector<int> sum(a.size());
    sum[0] = a[0];
    //计算前缀和
    for (int i = 1; i < a.size (); i++) {
        sum[i] = sum[i - 1] + a[i];
    }
    // 输出前缀和数组
    for (int i = 0; i < a.size (); i++) {
        cout << sum[i] << " ";
    }
    cout << endl;
    return 0;
}

当然也可以用库函数,不过作者感觉没什么用(需要对库函数掌握得十分滴熟练)

#include<iostream>
#include<vector>
#include<numeric>
using namespace std;
int main() {
	vector<int> arr = { 1,2,3,4,5 };
	vector<int> sum(arr.size());
	partial_sum(arr.begin(), arr.end(), sum.begin());
	for (int i = 0; i < arr.size(); i++)cout << sum[i] << " ";
	return 0;
}

 在某些情况下还能再简单,即在原数组中计算,减少空间复杂度

#include <iostream>
#include <vector>
using namespace std;
int main() {
    vector<int> a = { 1, 2, 3, 4, 5 };
    int n = a.size();
    for (int i = 1; i < n; i++) {
        a[i] = a[i - 1] + a[i];
    }
    for (int num : a) {
        cout << num << " ";
    }
    return 0;
}

前缀和有什么用?

1、区间求和

给定一个区间,例如【1,3】,求数组在此区间上的和

#include <iostream>
#include <vector>
using namespace std;
int main() {
    vector<int> a = { 1, 2, 3, 4, 5 };
    vector<int> sum(a.size());
    int left = 1;
    int right = 3;
    sum[0] = a[0];
    for (int i = 1; i < a.size (); i++) {
        sum[i] = sum[i - 1] + a[i];
    }
    //求区间和
    cout << (sum[right] - sum[left-1]) << endl;
    return 0;
}

 这里有一个特例,就是当left为0的时候,left-1就越界了

提供两个解决方法,一个是用if(left==0)特判,另一个是原数组从下标为1的位置开始存储(推荐)

注意不能写成sum[right] - sum[left]

2、前缀积(和前缀和差不多)

求区间【1,3】的前缀积就是sum[right]-sum[left-1]

前提是前缀积不能溢出

高精度计算中通常会对前缀积进行取模

sum[i]=(sum[i-1]*arr[i])%mod

感兴趣的可以搜一下乘法逆元/费马小定理/快速幂(其实是作者不会)

3、异或和

求区间【1,3】的异或和就是sum[right]^sum[left-1]

#include<iostream>
#include<vector>
using namespace std;
int main() {
	vector<int> arr = { 2,2,7,5,7,2,1,4,1,5 };
	vector<int> s(arr.size());
	s[0] = arr[0];
	for (int i = 1; i < arr.size(); i++) {
		s[i] = s[i - 1] ^ arr[i];
	}
	for (int i = 0; i < arr.size(); i++) {
		cout << s[i] << " ";
	}
	return 0;
}

 

前缀异或和数字相同=这段区间异或和为0

比如上图异或和中有2个7,就代表原数组5,7,2这3个数的异或和为0

实战 

洛谷P2004 领地选择

二维前缀和

#include<iostream>
#include<vector>
using namespace std;
int a[1050][1050], dp[1050][1050];
int main() {
	int n, m, c;
	cin >> n >> m >> c;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			cin >> a[i][j];
			dp[i][j] = dp[i][j - 1] + dp[i - 1][j] - dp[i - 1][j - 1] + a[i][j];

		}
	}
	int x = 0, y = 0;
	int MAX = -2147483648;
	for (int i = c; i <= n; i++) {
		for (int j = c; j <= m; j++)
		{
			int t = dp[i][j] - dp[i - c][j] - dp[i][j - c] + dp[i - c][j - c];
			if (t > MAX) {
				MAX = t;
				x = i - c + 1;
				y = j - c + 1;
			}
		}
	}
	cout << x << " " << y << endl;
	return 0;
}

http://www.dtcms.com/a/99054.html

相关文章:

  • 2两数相加解题记录
  • Nyquist插件基础:打印格式化字符串(LISP语言)
  • Java虚拟机(JVM)详解
  • 前端 vue 项目上线前操作
  • Spring Cache:简化缓存管理的抽象框架
  • MCP, LangChain、Dify 区别
  • 3.30日 001:中央海岸VS珀斯光荣
  • 操作系统 :进程概念
  • 集多功能为一体的软件,支持批量操作。
  • web权限划分提权和移权
  • 自行车模型与汽车模型的混合策略在自动驾驶中的多维度协同优化
  • graylog使用过程中的几个问题
  • 根据二叉树创建字符串
  • Linux的进程优先级调度学习笔记
  • 智慧运维平台:赋能未来,开启高效运维新时代
  • React 中props的不可变性,如何在组件中处理需要修改props的情况?
  • 每日一题 MySQL基础知识----(三)
  • 饮食 “妙方”,助力进行性核上性麻痹调养
  • 学校智慧路灯的主要功能有哪些?
  • Python第六章19:函数的多种参数类型对比
  • 【嵌入式学习3】零散知识点
  • 【C++篇】类与对象(上篇):从面向过程到面向对象的跨越
  • 【8】递归之经典题型总结
  • Redis6数据结构之String类型
  • DeepSeek本地部署(linux)
  • 零基础驯服GitHub Pages
  • Linux进程管理之子进程的创建(fork函数)、子进程与线程的区别、fork函数的简单使用例子、子进程的典型应用场景、父进程等待子进程结束后自己再结束
  • Elasticsearch 高级
  • 分库分表策略
  • Flutter:切换账号功能记录