请解决以下问题:给定一个长度为 NN 的数列,A_1,A_2, \cdots A_NA 1 ,A 2 ,⋯A N ,如果其中一段连续的子序列 A_i,A_{i+1}, \cdots A_j(i \le j)A i ,A i+1 ,⋯A j (i≤j) 之和是 KK 的倍数,我们就称这个区间 [i,j][i,j] 是 KK 倍区间。 你能求出数列中总共有多少个 KK 倍区间吗? 输入格式 第一行包含两个整数 NN 和 KK(1 \le N,K \le 10^5)(1≤N,K≤10 5 )。 以下 NN 行每行包含一个整数 A_iA i (1 \le A_i \le 10^5)(1≤A i ≤10 5 )。 输出格式 输出一个整数,代表 KK 倍区间的数目。
时间: 2024-04-07 17:33:38 浏览: 171
要求解数列中总共有多少个 KK 倍区间,可以使用前缀和和哈希表来解决。
首先,我们计算前缀和数组 prefix,其中 prefix[i] 表示数列从第一个元素到第 i 个元素的和。
然后,我们遍历前缀和数组,对于每个前缀和 prefix[i],我们计算该前缀和除以 KK 的余数 remainder。
我们使用一个哈希表 count 来记录每个余数出现的次数。初始时,哈希表中存在一个键值对 (0,1),表示前缀和为 0 的数量为 1。
接下来,我们遍历前缀和数组,对于每个前缀和 prefix[i],我们计算其余数 remainder,并在哈希表 count 中查找是否存在键值对 (remainder, cnt)。
如果存在,表示之前已经出现过相同的余数,那么说明从上次出现该余数的位置到当前位置之间的子序列的和是 KK 的倍数。所以,我们将 cnt 加到结果 res 上。
然后,我们更新哈希表 count 中键值对 (remainder, cnt) 的值为 cnt+1。
最后,返回结果 res 即可。
下面是实现了上述思路的代码:
```cpp
#include <iostream>
#include <unordered_map>
using namespace std;
int main() {
int N, K;
cin >> N >> K;
long long prefix = 0;
long long res = 0;
unordered_map<long long, int> count;
count[0] = 1;
for (int i = 0; i < N; i++) {
int num;
cin >> num;
prefix += num;
long long remainder = prefix % K;
if (remainder < 0) {
remainder += K;
}
if (count.find(remainder) != count.end()) {
res += count[remainder];
}
count[remainder]++;
}
cout << res << endl;
return 0;
}
```
这段代码的时间复杂度为 O(N),其中 N 是数列的长度。通过利用前缀和和哈希表,可以高效地求解 KK 倍区间的数量。
阅读全文