蓝桥杯 K倍区间 python

Posted 风信子的猫Redamancy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯 K倍区间 python相关的知识,希望对你有一定的参考价值。

蓝桥杯 K倍区间 python

题目描述

给定一个长度为 NN 的数列, A 1 , A 2 , ⋯ A N A_1, A_2, \\cdots A_N A1,A2,AN​​​,如果其中一段连续的子序列 $A_i,A_i+1,\\cdots A_j(i\\leq j) $​之和是 KK 的倍数,我们就称这个区间 [i, j][i,j] 是 K 倍区间。

你能求出数列中总共有多少个 KK 倍区间吗?

输入描述

第一行包含两个整数 N 和 K ( 1 ≤ N , K ≤ 1 0 5 ) ( 1 \\leq N,K \\leq 10^5) (1N,K105)

以下 N 行每行包含一个整数 A i ( 1 ≤ A i ≤ 1 0 5 ) A_i( 1 \\leq A_i \\leq 10^5) Ai(1Ai105)

输出描述

输出一个整数,代表 K 倍区间的数目。

输入输出样例

示例

输入

5 2
1
2
3
4
5

输出

6

运行限制

  • 最大运行时间:2s
  • 最大运行内存: 256M

解题思路

思路也很简单,简单来说,就是得到每一个和,我们可以利用前缀来求,比如我们得到了一个sum的数组,[i,j]区间的和也就是sum[j] - sum[i-1],这样我们就可以得到我们的和,然后判断和是否能够%K为0,如果能就计数+1

但是毫无疑问,这样做是一定会TLE的,无法AC的

看了一些大佬的思路,这里面用了一些数学的知识

当区间和对K取模等于0即 ( sum[j]-sum[i-1] )%K= 0 ( 化为sum[j]%K=sum[i-1] %K ) 时此区间满足条件要求。

所以对每个sum[i],求其值时顺求其对K的取模,最后得到一模数列,方便计算。

得到模数列,需选取模数列中的相同模进行组合,但题目限制了时空复杂度,此行不可行。

以题目中的第一个测试用例为例,求得模数列为 1 1 0 0 1

手动组合体验一下组合过程:

首元素 1 本身组合不了

第二个 1 可以与前面一个 1 组合

第三个元素 0 本身组合不了

第四个元素 0 可以与第三个元素 0 组合

第五个元素 1 可以与前面两个1 组合两次。(可以看出只要迭代加上前面已经出现过的相同模即可,假如存在第六个元素 1 ,此时它前面有 3 个 模 1 ,它可以与他们3个一一组合,一共在3种情况,所以加上3即可)

注意:模为0的情况,其本身不需要和其他0进行组合,因为他们不用和其他模相等(相减),自己这个数列本身就满足K倍。

代码

import os
import sys

# 请在此输入您的代码
N,K = map(int,input().split())
ans = 0
cnt = [0]*K

for i in range(N):
  num = int(input())
  ans += num
  cnt[ans%K] += 1

ans = cnt[0]
for i in range(0,K):
  if cnt[i]:
    ans += cnt[i] * (cnt[i] - 1)//2

print(ans)

有时候,可能在看题解的时候,会发现有人把 c n t [ 0 ] cnt[0] cnt[0]​​ 设为1,直接初始化为1进行求解,得到的结果是正确的,这也涉及到一些数学知识,在前面的思路过程中,我们说,我们需要对模为0的直接进行一个加和,比如说,模为0的有m个,他们的组合是 C m 2 C_m^2 Cm2​​ 个,由于模为0本身也是一种情况,所以说,得到的组合和本身就是 C m 2 + m C_m^2 + m Cm2+m​​ 个,这里我们就可以有一个数学的公式转化
C m 2 + m = m ∗ ( m − 1 ) 2 + m = m ( m − 1 2 + 1 ) = ( m + 1 ) ∗ m 2 = C m + 1 2 C_m^2 + m = \\fracm*(m-1)2 + m = m(\\fracm-12 + 1) = \\frac(m+1)*m2 = C_m+1^2 Cm2+m=2m(m1)+m=m(2m1+1)=2(m+1)m=Cm+12

所以对于我们的计算来说,我们可以一开始就将第一个置为0,我们也可以进行加和,两者结果是相等的

以上是关于蓝桥杯 K倍区间 python的主要内容,如果未能解决你的问题,请参考以下文章

2017蓝桥杯 K倍区间 前缀和+同余定理

第八届蓝桥杯-k倍区间

2017蓝桥杯第十题(k倍区间)

题集k倍区间(抽屉原理)

LQ0065 k倍区间前缀和+余数定理

算法笔记_079:蓝桥杯练习 区间k大数查询(Java)