数组中的"Maximum Sum mod M"范围:求和和计数

"Maximum Sum mod M" ranges in an array: sum and count

本文关键字:求和 范围 mod Maximum Sum 数组      更新时间:2023-10-16

>问题

给定数组A = a0,a1,...an,大小最大为 N ≤ 10^5,0 ≤ ai≤ 10^9。
和数字0

任务是找到最大∑(k=i, j) a k % M = (a i + a i+1 + a(i+2) + ⋯ + a(j−1) + a(j)) % M,以及有多少个不同的范围(i,j)得到这个总和。

复杂度必须小于O(N^2),后者太慢。

N= 3,M= 5

A= {2, 4, 3}

最大总和 mod M4,有 2 个范围,分别是021

我的尝试

让我们定义s[j] = (a0+ a1+ ... + a j) % M所以如果你想要以 j 结尾的最佳和,你必须选择一个 s[i] i 是比你高的最小和。

因为如果s[i]> s[j]; s[i] = M - K;K] 接近s[j]时,它将增加结果模M

这个想法是我的尝试,首先你必须计算从 0 开始并以索引 i 结束的所有总和,然后你可以通过使用地图已经lower_bound有的二叉搜索来搜索值,并计算你可以用你找到的值做多少次求和。你必须把总和放在某个地方,以计算你能做多少次。

#include <iostream>
#include <map>
#define optimizar_io ios_base::sync_with_stdio(false);cin.tie(NULL);
using namespace std;
const int LN = 1e5;
long long N, M, num[LN];
map < long long, int > sum;
int main() {
optimizar_io
cin >> N >> M;
sum[0]++;
long long cont = 0, tmax = 0, res = 1, val;
map < long long, int > :: iterator best;
for (int i = 0; i < N; i++)
{
cin >> num[i];
cont = (cont + num[i]) % M;
if (tmax == cont)
res += sum[0];
if (tmax < cont)
tmax = cont, res = sum[0];
best = sum.lower_bound(cont + 1);
if (best != sum.end())
{
val = cont - (*best).first + M;
if (tmax == val)
res += (*best).second;
if (tmax < val)
tmax = val, res = (*best).second;
}
sum[cont]++;
}
cout << tmax << " " << res;
return 0;
}