数组中的“最大总和模M”范围:总和和计数

时间:2018-04-08 19:48:53

标签: c++

问题

给定一个数组 A = a0,a1,... a ,大​​小最大为N≤10^ 5 0≤a≤10^ 9。
数字 0< M≤10^ 9。

任务是找到最大值Σ(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}

最大总和模式M 4 2 范围, a 0 2 a 1

我的尝试

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

因为如果 s [i]> S [J]。 s [i] = M - K; K< M - s [j] 那么结果和范围将是(s [j] -s [i] + M)%M =(s [j] + K)%M 因为 K< M - s [j] 它会增加结果 mod M ,并且当 s [j] 更接近 s [j] 它会增加结果 mod M

1 个答案:

答案 0 :(得分:0)

这个想法是我的尝试,首先你必须要计算从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;
}