目录
题解
1. 最开始我直接前缀和+暴力遍历,只能过28%的数据
2. 然后开始优化,我们让每个前缀和数组都%k,这样会得出一个余数,通过数学性质可得,如果两个数%k的余数相等,如果两数相减,那么一定是k的倍数,比如:
3 % 2 = 1
7 % 2 = 1
然后 (7-3)%2 =0
所以满足k的倍数
3. 于是直接先把为0的全部加一点,但是有一点需要注意,为0的也可以相互之间减,然后得到k的倍数(前缀和两个位置相减 = 这一段的和)
4. 于是代码如下:
n,k = map(int,input().split())
a = [0]
for i in range(0,n):
s = int(input())
a.append(s)
# print(a)
b = [0]
for i in range(1,n+1):
b.append(a[i] + b[i-1]) # 求前缀和
cnt = 0
# print(b)
for i in range(1,n+1):
b[i] = b[i] % k # 求与k的余数
cnt += b.count(0)-1
dic = {}
for i in b[1:]:
dic[i] = 0
for i in b[1:]:
dic[i] += 1 # 统计余数的个数
for k,v in dic.items():
cnt += v * (v-1) // 2 # Cm2:多项式
print(cnt)
cnt += v * (v-1) // 2: 这个地方主要就是多项式的一个计算,因为我们现在有很多个余数相同的数,要从里面任意找两个数进行组合,所以就是Cm2,然后通过Cmn = m!/ (n! * (m-n)!),推导出Cm2 = v * (v-1) // 2