关于前缀和的个人理解

前缀和,就是计算从开始到结束所有值的总和。

在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]

其实这里表示一个矩形中所有数字的和就是上面这个函数,其实就是用两个坐标来表示矩形,然后再用容斥原理来进行计算

以上就是最基本的关于前缀和的内容,点赞支持一下博主,来更新更优质的内容

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值