974. 和可被 K 整除的子数组

给定一个整数数组 A,返回其中元素之和可被 K 整除的(连续、非空)子数组的数目。
示例:
输入:A = [4,5,0,-2,-3,1], K = 5
输出:7
解释:
有 7 个子数组满足其元素之和可被 K = 5 整除:
[4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3]
提示:
1 <= A.length <= 30000
-10000 <= A[i] <= 10000
2 <= K <= 10000

解题思路

通常,涉及连续子数组问题的时候,我们使用前缀和来解决它们。连续子数组的和就可以表示为前缀和的差,比如 sum(A[i : j + 1]) = s[j + 1] - s[i]。
**定义前缀和数组长度时最前面添加一个为0的项,为了包含前缀和刚好为K的倍数的情况。**因为取模的时候要作差来求,如果前缀和中刚好有一个为k的倍数,所以这个数减去添加的0刚好还是能整除k。
同余定理:如果(a-b)/k为整数,则称a和b对整数k同余(即余数相同)
最后,从余数相同的数里取出两个进行组合,得到的总的组合方式就是结果。
组合公式:
在这里插入图片描述

class Solution(object):
    def subarraysDivByK(self, A, K):
        """
        :type A: List[int]
        :type K: int
        :rtype: int
        """
        # 求连续数组的和,连续数组的和可以表示为前缀和的差,比如 sum(A[i : j + 1]) = s[j + 1] - s[i]
        s = [0] * (len(A) + 1) # s表示前缀和,长度为len(A) + 1),为了包含前缀和刚好为k的倍数的情况
        kcnt = [0] * K # kcnt[i]代表s中有多少个元素 mod K 为i,索引代表余数值,数值表示余数为i的个数
        # 求前缀和 
        for i in range(len(A)):
            s[i + 1] = s[i] + A[i]
        # 如果(a-b)/k为整数,则称a和b对整数k同余(即余数相同)
        for item in s:
            kcnt[item % K] += 1 
        # 两个前缀和余数相同,说明他们的差能够整数k,即他们之间的子数组和能够整数k
        # 使用组合公式计算
        return sum(x * (x - 1) // 2 for x in kcnt)
在Python中,要判断一个八位数是否能被2、5、8、9、11整除,可以通过编写一个函数来实现。由于八位数范围是10000000到99999999,我们可以编写一个函数遍历这个范围内的每一个数,然后检查它是否能被这些数整除。 这里有一个小技巧,因为8是2的三次幂,所以如果一个数能被8整除,那么它肯定也能被2整除。另外,如果一个数能被9整除,那么它所有位数上的数字加起来的和也能被9整除。对于11,有一个简单的检查规则:如果一个数从左到右的奇数位上的数字之和与偶数位上的数字之和的差能被11整除,那么这个数也能被11整除。 以下是实现这个判断的Python代码示例: ```python def is_divisible_by_258911(number): # 检查是否能被8整除(因为能被8整除的数也一定能被2整除) if number % 8 != 0: return False # 检查是否能被9整除(所有位数之和) if sum(int(digit) for digit in str(number)) % 9 != 0: return False # 检查是否能被11整除(奇数位和偶数位的差) if abs(sum(int(digit) for i, digit in enumerate(str(number)) if i % 2 == 0) - sum(int(digit) for i, digit in enumerate(str(number)) if i % 2 != 0)) % 11 != 0: return False # 检查是否能被5整除(以0或5结尾) if number % 10 not in [0, 5]: return False return True # 遍历八位数的范围 for i in range(10000000, 100000000): if is_divisible_by_258911(i): print(f"{i} 是能被2, 5, 8, 9, 11整除的八位数。") ``` 这段代码将遍历所有的八位数,并使用`is_divisible_by_258911`函数检查每个数是否满足条件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值