Given an array A of integers, return the number of (contiguous, non-empty) subarrays that have a sum divisible by K.
Example 1:
Input: A = [4,5,0,-2,-3,1], K = 5
Output: 7
Explanation: There are 7 subarrays with a sum divisible by
K = 5:
[4, 5, 0, -2, -3, 1], [5], [5, 0],
[5, 0, -2, -3], [0], [0, -2, -3],
[-2, -3]
Note:
1.1 <= A.length <= 30000
2.-10000 <= A[i] <= 10000
3.2 <= K <= 10000
给定一个集合,求这个集合中子集的个数,其中对子集的要求是子集中元素的和能被k整除。
记数组pre[i+1]表示前 i 位元素的和mod k 的结果,且规定pre[0]=0。
现假设pre数组中有两个位置 i , j (1<=i<j)上的结果相同,即表示原集合中前 i-1 位和前 j-1 位元素的和 mod k 的值相同,易知从 i-1 到 j-1 位构成的子集中元素的和一定能被 k 整除。
利用这一结论,现只需要统计数组前缀和余数相同的个数,再从余数相同的位置上任选两个位置构成子集,并计算个数
如上图所示,若计算这个集合中子集个数,只需计算分别从前缀和求余结果为 0 和 4 的位置上,可以挑选出多少对不同的组合,这一结果可以利用组合数求出
Ps:注意前缀和为负的情况,c++中对其求余仍未负数
class Solution {
private:
vector<int> num;
vector<int> pre;
public:
int subarraysDivByK(vector<int>& A, int k) {
int len=A.size();
num.resize(k+5,0);
pre.push_back(0);
for(register int i=0;i<len;i++)
pre.push_back(pre[i]+A[i]);
for(auto ele : pre)
num[(ele%k+k)%k]++;
int ans=0;
for(register int i=0;i<k;i++){
ans+=num[i]*(num[i]-1)/2;
}
return ans;
}
};