用简单C语言实现给定一个长度为N的数列,A1, A2, … AN,如果其中一段连续的子序列Ai, Ai+1, … Aj(i <= j)之和是K的倍数,我们就称这个区间[i, j]是K倍区间。 你能求出数列中总共有多少个K倍区间吗? 输入格式 第一行包含两个整数N和K。(1 <= N, K <= 100000) 以下N行每行包含一个整数Ai。(1 <= Ai <= 100000) 输出格式 输出一个整数,代表K倍区间的数目。
时间: 2024-02-13 09:00:05 浏览: 35
以下是简单C语言实现的代码:
```c
#include <stdio.h>
#include <stdlib.h>
#define MAXN 100000
int N, K;
int A[MAXN + 1];
int S[MAXN + 1];
int main() {
scanf("%d%d", &N, &K);
for (int i = 1; i <= N; i++) {
scanf("%d", &A[i]);
S[i] = (S[i - 1] + A[i]) % K;
}
int cnt[K];
for (int i = 0; i < K; i++) {
cnt[i] = 0;
}
cnt[0] = 1;
long long ans = 0;
for (int i = 1; i <= N; i++) {
ans += cnt[S[i]];
cnt[S[i]]++;
}
printf("%lld\n", ans);
return 0;
}
```
其中,我们使用cnt数组来记录余数出现的次数,并根据公式计算答案。在计算答案过程中,我们可以直接累加cnt[S[i]]的值,因为这个值表示可以与当前位置形成K倍区间的前缀数。最后,输出答案即可。
相关问题
用简单C语言实现给定一个长度为N的数列,A1, A2, … AN,如果其中一段连续的子序列Ai, Ai+1, … Aj(i <= j)之和是K的倍数,我们就称这个区间[i, j]是K倍区间。 你能求出数列中总共有多少个K倍区间吗? 输入格式 第一行包含两个整数N和K。(1 <= N, K <= 100000) 以下N行每行包含一个整数Ai。(1 <= Ai <= 100000) 输出格式 输出一个整数,代表K倍区间的数目。
这是一个算法问题,以下是 C 语言实现的代码:
```c
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n, k, i, j, sum = 0, ans = 0;
scanf("%d%d", &n, &k);
int* a = (int*)malloc(sizeof(int) * n);
int* s = (int*)calloc(n + 1, sizeof(int));
int* count = (int*)calloc(k, sizeof(int));
for (i = 0; i < n; i++)
{
scanf("%d", &a[i]);
s[i + 1] = s[i] + a[i];
s[i + 1] %= k;
}
for (i = 0; i <= n; i++)
{
ans += count[s[i]];
count[s[i]]++;
}
printf("%d\n", ans);
free(a);
free(s);
free(count);
return 0;
}
```
解释:
先输入 n 和 k,分别表示数列的长度和倍数。然后用动态数组 a 存储数列中的数。为了计算子序列之和,我们再用动态数组 s 存储前缀和,即 s[i] 表示前 i 个数的和。注意,为了方便计算,s 数组的下标从 1 开始。
接下来,我们需要计算每个子序列之和是否是 k 的倍数,可以通过计算前缀和之差的方式来实现。即如果 s[j] - s[i] 是 k 的倍数,那么区间 [i+1, j] 就是 k 的倍数区间。
为了统计 k 的倍数区间的个数,我们可以使用桶排序的思想,创建一个大小为 k 的 count 数组,count[i] 表示前 i 个数中余数为 i 的数的个数。遍历前缀和数组 s,对于每个 s[i],我们将 count[s[i]] 的值加到答案 ans 中,然后再将 count[s[i]] 的值加 1。
最后输出答案 ans 即可。
注意:为了避免数组越界,我们需要将 s 数组的大小设为 n+1,而不是 n。同时,我们需要在释放动态数组的时候,先释放 a 数组,再释放 s 数组和 count 数组。
用C语言实现给定一个长度为N的数列,A1, A2, … AN,如果其中一段连续的子序列Ai, Ai+1, … Aj(i <= j)之和是K的倍数,我们就称这个区间[i, j]是K倍区间。 你能求出数列中总共有多少个K倍区间吗? 输入格式 第一行包含两个整数N和K。(1 <= N, K <= 100000) 以下N行每行包含一个整数Ai。(1 <= Ai <= 100000) 输出格式 输出一个整数,代表K倍区间的数目。
这是一个经典的问题,可以使用前缀和和哈希表来解决。具体步骤如下:
1. 使用前缀和算法求出每个位置的前缀和,即sum[i]表示前i个数的和。
2. 对前缀和数组进行模K运算,得到余数数组mod[i],即mod[i] = sum[i] % K。
3. 使用哈希表记录每个余数第一次出现的位置,即hash[mod[i]] = min(hash[mod[i]], i)。
4. 遍历余数数组mod,如果mod[i]为0,则区间[1, i]是K倍区间。否则,如果hash[mod[i]]存在,则区间[hash[mod[i]]+1, i]是K倍区间。
5. 统计所有的K倍区间即可。
C语言代码如下:
```c
#include <stdio.h>
#include <string.h>
#define MAXN 100005
#define INF 0x3f3f3f3f
int n, k;
int a[MAXN], sum[MAXN], mod[MAXN], hash[MAXN];
int main() {
scanf("%d%d", &n, &k);
memset(hash, INF, sizeof(hash));
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
sum[i] = sum[i-1] + a[i];
mod[i] = sum[i] % k;
}
hash[0] = 0;
int ans = 0;
for (int i = 1; i <= n; i++) {
if (mod[i] == 0) {
ans += 1;
} else {
if (hash[mod[i]] < INF) {
ans += hash[mod[i]]+1;
}
}
hash[mod[i]] = fmin(hash[mod[i]], i);
}
printf("%d\n", ans);
return 0;
}
```
相关推荐
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)