Python前缀和(例题:异或和,求和)
前缀和
前缀和:对于一个长度为n的列表a,前缀和为:
sum[i]=a[0]+a[1]+...+a[i]
前缀和的性质:
第一条性质用于处理出前缀和:
Sum[i]=Sum[i-1]+a[i]
第二条性质可以在O(l)的时间内求出区间和:
a[l]+....+a[r] =Sum[r]-Sum[l-1]
前缀和模板标准写法
def get_persum(a): #下标从0开始
n=len(a)
sum=[0]*n
sum[0]=a[0]
for i in range(1,n):
sum[i]=sum[i-1]+a[i]
#快速求区间之和
def get_sum(sum,l,r):
if l==0:
return sum[r]
else:
return sum[r]-sum[l-1]
a=[1,2,3,4,5]
print("a=",a)
print("sum=",sum)
例题1: 异或和—位运算
题目描述
给定一个数组 Ai,分别求其每个子段的异或和,并求出它们的和。或者说,对于每组满足 1≤L≤R≤n的 L, R,求出数组中第 L 至第 R 个元素的异或和。然后输出每组 L, R 得到的结果加起来的值。
输入格式
输入的第一行包含一个整数 nn。
第二行包含 n 个整数 Ai,相邻整数之间使用一个空格分隔。
输出格式
输出一行包含一个整数表示答案。
样例输入
5
1 2 3 4 5
样例输出
39
代码实现:
这个用前缀和写的代码可以通过90%,简单好理解并且拿到的分比较高
n=int(input())
a=list(map(int,input().split()))
ans=0
for L in range(n):
sum1=0
for R in range(L,n):
sum1^=a[R]
ans+=sum1
print(ans)
这个是100%通过的代码
n = int(input())
a = [int(x) for x in input().split()]
ans = 0
for k in range(21): # 所有a不超过20位
zero, one = 1, 0 # 统计第k位的0和1的数量
cnt, sum = 0, 0 #cnt用于统计第k位有多少对si⊕sj =1
for i in range(n):
v = (a[i] >> k) & 1 # 取a[i]的第k位
sum ^= v # 对所有a[i]的第k位做异或得到sum,sum等于0或者1
if sum == 0: # 前缀和为0
zero += 1 # 0的数量加1
cnt += one # 这次sum=0,这个sum跟前面等于1的sum异或得1
else: # 前缀异或为1
one += 1 # 1的数量加1
cnt += zero # 这次sum=1,这个sum跟前面等于0的sum异或得1
ans += cnt * (1 << k) # 第k位的异或和相加
print(ans)
例题 2:求和
代码
利用前缀和思想求后缀和,计算后缀和数组C,C1为a2到an的和,C2为 a3到an的和
n=int(input())
a=list(map(int,input().split()))
ans=0
c=[0]*n
c[0]=sum(a)-a[0]
for i in range(1,n):
c[i]=c[i-1]-a[i]
for i in range(n):
ans+=a[i]*c[i]
print(ans)