前缀和,就是计算从开始到结束所有值的总和。
在python中,计算前缀和有以下几种方法,
第一种,是最直接的计算方法,导包,使用itertools里面的accumulate函数。
如下示例
from itertools import accumulate
list1=[1,2,3,4,5]
print(list(accumulate(list1)))
还有就是使用递推关系式来处理
前缀和的递推公式就是
sum[i+1]=sum[i]+a[i+1]
那么同样,我们可以用这样一个公式,在O(n)的时间里面计算出前缀和
def func(list1):
ans=[0]*len(list1)
ans[0]=list1[0]
for i in range(len(list1)-1):
ans[i+1]=ans[i]+list1[i+1]
return ans
print(list(func(list1)))
这样子,就可以求出来前缀和的列表
前缀和也可以用来求区间和,那么,这里其实就是类似容斥原理
sum(i,j)=sum(0,r)-sum(0,l-1)
其实,也就可以用一下函数来表示
def get_sum(list1,l,r):
if l==0:
return list1[r]
else:
return list1[r]-list1[l-1]
但是,这里因为l-1会超出列表范围,所以说会要分类讨论一下
那么这里就是基本的关于前缀和的内容,但是,究竟怎么去运用呢?,就要去看一些具体的题目实现
先看第一个,这个是一个比较基础的题目,但是很具有启发性
那么,这道题有没有数字,和前缀和又有什么关系呢
其实可以把L视为1,Q视为-1,那么平衡串就是区间相加为0的串,那么这样子就可以开始去计算了
下面便是代码
#最长平衡串
string1=input()
list1=[]
from itertools import accumulate
for i in string1:
if i=='L':
list1.append(1)
else:
list1.append(-1)
list1_accumulate=list(accumulate(list1))
def get_sum(list1_accumulate,l,r):
if l==0:
return list1_accumulate[r]
else:
return list1_accumulate[r]-list1_accumulate[l-1]
ans=-1
for l in range(len(list1_accumulate)):
for r in range(l,len(list1_accumulate)):
if get_sum(list1_accumulate,l,r)==0:
ans=max(ans,r-l+1)
print(ans)
下面就来解释一下这一代码,这里面首先就是去将L和Q来进行转换,产生1 和-1,接着就是将这一列表的前缀和给求出来,然后就是求区间和,区间和就是使用get_sum函数,最后将ans设置为-1,(其实是啥都没关系,要一个足够小的数就可以了),然后再使用就是去打印出ans,这里就是一个用双重for循环来检索,并且用距离计算公式来处理,最后不断用max函数更新就可以了。
下面一题就是更复杂的一类,求区间次方和
这道题数据范围k为1-5(截不下,就在这里补充一下)
那么既然数字是1-5,其实可以用一个列表,将其给存储起来,即存放输入列表的一次方,二次方,一直到5次方,然后再让1 3 这样的start 和end表示区间的范围就可以了,
下面是代码
#区间次方和
from itertools import accumulate
n,m=map(int,input().split())
a=[0]+list(map(int,input().split()))
num=1000000007
def presum(a):
list1=list(accumulate(a))
return list1
list1_ans=[]
for i in range(1,6):
list1_ans.append(presum([x**i for x in a]))
def get_sum(a,l,r):
if l==0:
return a[r]-a[0]
else:
return (a[r]-a[l-1]+num)%num
for i in range(m):
s,e,k=map(int,input().split())
print(int(get_sum(list1_ans[k-1],s,e)))
最后就是关于二维前缀和的事情,因为数组一维的时候其实就是两数相减就可以了,但是二维的计算就会更加复杂一点,那么如何解决呢,其实这里是要用容斥原理来处理这一问题
那么对于二维前缀和,要使用两个坐标,分别为i和j来表示位置
于是就可以有以下函数来表示前缀和
def sum_matrix(matrix):
m=len(matrix)
n=len(matrix[0])
ans_matrix=[[0]*(n+1) for _ in range(m+1)]
print(ans_matrix)
for i in range(1,m+1):
for j in range(1,n+1):
ans_matrix[i][j]=ans_matrix[i-1][j]+ans_matrix[i][j-1]-ans_matrix[i-1][j-1]+matrix[i-1][j-1]
return ans_matrix
从容斥原理来看,其实就是将前面两个矩阵相加在减去相邻的部分就可以了,那么既然如此,那么如何去求任意一个区间的集合。
def ans(sum_matrix,x1,y1,x2,y2):
return sum_matrix[x2][y2]-sum_matrix[x1-1][y2]-sum_matrix[x2][y1-1]+sum_matrix[x1-1][y1-1]
其实这里表示一个矩形中所有数字的和就是上面这个函数,其实就是用两个坐标来表示矩形,然后再用容斥原理来进行计算
以上就是最基本的关于前缀和的内容,点赞支持一下博主,来更新更优质的内容