1.前缀和,遍历每个区间,TLE
/*
*/
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 1e5 + 10;
int n, k;
int a[N], s[N];
int res = 0;
int main()
{
scanf("%d%d", &n, &k);
// 初始化前缀和数组
s[0] = 0;
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
s[i] = s[i - 1] + a[i];
}
for(int i = 1; i <= n; i++)
for(int j = i; j <= n; j++)
{
if((s[j] - s[i - 1]) % k == 0 ) res++;
}
cout << res << endl;
return 0;
}
2.数学思想优化
/*
数据量1e5, 时间复杂度O(n)或者O(n * log(n))
前缀和:O(1)
优化:
两个前缀和的模相等,就可以构成一个k倍空间
*/
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 1e5 + 10;
// int类型最大值约为2e9,为了防止可能前缀和越界,使用Long Long
typedef long long LL;
int n, k;
// cnt[N]:表示余数为N的数有多少个
LL s[N], cnt[N];
LL res = 0;
int main()
{
scanf("%d%d", &n, &k);
// 初始化前缀和数组
s[0] = 0;
for(int i = 1; i <= n; i++)
{
scanf("%lld", &s[i]);
s[i] += s[i - 1];
}
// 空区间,和为0,% k 也是0,也算一个
cnt[0] = 1;
for(int i = 1; i <= n; i++)
{
res += cnt[s[i] % k];
cnt[s[i] % k] ++;
}
cout << res << endl;
return 0;
}