第二天:前缀和
给定一个长度为 N 的数列,\(A_1,A_2,…A_N\) 如果其中一段连续的子序列 \(Ai,Ai+1,…Aj\) 之和是 K 的倍数,我们就称这个区间 \([i,j]\)是 K倍区间。
你能求出数列中总共有多少个 K 倍区间吗?
输入格式
第一行包含两个整数 N和 K。
以下 N行每行包含一个整数 \(A_i\)。
输出格式
输出一个整数,代表 K倍区间的数目。
数据范围
1≤ N,K ≤100000
1≤ \(A_i\) ≤100000
输入样例:
5 2
1
2
3
4
5
输出样例:
6
思路
(x - y) % k = 0
x % k = y % k
考虑前缀和,\(sum[i,j] = pre[j] - pre[i - 1]\)
使用哈希表记录pre % k 出现的次数,对于当前下标j,如果统计 pre[j] % k 出现的次数加入答案,之后将pre[j] % k加入哈希表!
代码
import sys
from collections import Counter
sys.setrecursionlimit(1000000)
input = lambda: sys.stdin.readline().strip()
r1 = lambda: int(input())
r2 = lambda: map(int, input().split())
r3 = lambda: [*map(int, input().split())]
def solve():
N,K = r2()
a = [0] * (N + 1)
for i in range(1,N + 1):
a[i] = r1()
a[i] += a[i - 1]
cnt = Counter()
ans = 0
# 此处cnt[0] = 1一定要加入,因为pre[0] = 0,如果pre[i] % k = 0,那么说明[1,i]为k倍区间
cnt[0] = 1
for i in range(1,N + 1):
ans += cnt[a[i] % K]
cnt[a[i] % K] += 1
print(ans)
if __name__ == "__main__":
t = 1
for _ in range(t):
solve()
二维前缀和模板总结
for i in range(1, n + 1):
for j in range(1, m + 1):
a[i][j] += (a[i][j - 1] + a[i - 1][j] - a[i - 1][j - 1])
def query(x1, y1, x2, y2):
return a[x2][y2] - a[x2][y1 - 1] - a[x1 - 1][y2] + a[x1 - 1][y1 - 1]

浙公网安备 33010602011771号