第二天:前缀和

给定一个长度为 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]
posted @ 2024-03-01 14:27  gebeng  阅读(23)  评论(0)    收藏  举报