113082024-08-08 00:22:25kukkermanMaximális szorzat (50 pont)cpp17Futási hiba 40/5061ms2916 KiB
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdint>

void beolvas(std::istream &be, std::vector<int64_t> &v, int &k, int &b) {
    int n;
    be >> n >> k >> b;

    v.resize(n);
    for (auto &x : v) {
        be >> x;
    }
}

void feldolgoz(std::vector<int64_t> &v, int k, int negativ) {
    using std::cout;
    
    static const int64_t M = 1000000007;
    const auto n = static_cast<int>(v.size());

    sort(v.begin(), v.end());

    // Megkeressuk az elso nemnegativ szam poziciojat
    auto p = static_cast<int>(lower_bound(v.begin(), v.end(), 0) - v.begin());

    // Ha a feltetel tobb negativ szamot kovetel meg, mint ahany
    // eredetileg a sorozatban talalhato, akkor nincs megoldas.
    if (p < negativ) {
        cout << "-1\n";
        return;
    }

    // A 0-hoz legkozelebb eso negativ szamtol kezdve megprobalunk annyit
    // 0-ig novelni, hogy hogy pontosan az eloirt darabszamu maradjon.
    for (; p > negativ && k >= 0; p--) {
        // Levonjuk 'k'-bol az aktualis negativ szam 0-ig novelesenek koltseget.
        k += static_cast<int>(v[p - 1]);
        v[p - 1] = 0;
    }

    // Ha nincs elegendo valasztasunk ahhoz, hogy "eltuntessuk" a megfelelo darabszamu
    // negativ szamot, akkor nincs megoldas.
    if (k < 0) {
        cout << "-1\n";
    }

    // Kiszamitjuk az elso nemnegativ szamtol kezdodoen egeszen a sorozat vegeig
    // az egyes elemek osszeget:
    // ps[i] = az elso 'i' db. elem osszege az elso nemnegativ szamtol kezdodoen
    std::vector<int64_t> ps(n - p + 1);
    for (int i = p; i < n; i++) {
        ps[i - p + 1] = ps[i - p] + v[i] - v[p];
    }

    // Binaris kereses segitsegevel megkeressuk az elso olyan elem poziciojat,
    // amennyire mar eppen nem potolhatok ki a sorozat elemei az elso nemnegativ
    // elemtol kezdodoen. Pl.:
    // 
    // Legyen v = { -2, -1, 1, 3, 4 }, k = 3
    // 
    // Az elso nemnegativ elem pozicioja (p = 2). 2 db. valasztassal a sorozat
    // kipotolhato egeszen a 3. pozicioig: v = { -2, -1, 1 + 2, 3, 4 },
    // azonban ahhoz, hogy a 4. pozicioig kipotoljuk a sorozatot 4 valasztasra
    // lenne szukseg: v = { -2, -1, 1 + 3, 3 + 1, 4 }, azaz a 4. az elso olyan
    // pozicio, ameddig mar eppen nem potolhato ki 'k' db. valasztasbol.
    int b = p, e = n;
    while (b < e) {
        const auto m = b + (e - b) / 2;
        // A 'p'-edik elemtol az 'm'-edik elemig 'v[m]'-re valo kipotlasanak
        // koltsege.
        const auto x = (v[m] - v[p]) * (m - p + 1) - ps[m - p + 1];

        if (k < x) {
            e = m;
        } else {
            b = m + 1;
        }
    }

    // Levonunk 'k'-bol annyit, amennyi elegendo az elemek kipotoloasahoz
    // a 'p'-ediktol, az 'e-1'-edikig 'v[e-1]'-re. 
    k -= static_cast<int>((v[e - 1] - v[p]) * (e - p) - ps[e - p]);

    // Az e = n esetben, azaz amikor a sorozat kipotolhato egeszen az utolso
    // 'n-1'-edik elemig, elofordulhat, hogy 'k' elegendoen nagy ahhoz, hogy
    // akar 1-nel tobbel is novelhetjuk meg az utolso elemet is. Az 'x' erteke
    // egyenlo lesz azzal az ertekkel, amelyre vegul kipotoljuk a sorozatot
    // 'p'-tol 'e-1'-ig.
    const auto x = v[e - 1] + k / (e - p);

    // Elkezdjuk kiszamitani a modositott vektor elemeinek a szorzatat, ugyelve
    // arra, hogy ne tortenjen tulcsordulas a szorzassoran.
    int64_t s = 1;

    // Osszeszorozzuk a megmaradt negativ elemeket.
    int i;
    for (i = 0; i < p; i++) {
        s = (s * -v[i]) % M;
    }

    // Osszesen 'k % (e - p)' db. olyan elem lesz, amely meg tovabb novelheto
    // eggyel, azaz amelyeknek az erteke igy 'x+1' lesz.
    for (auto j = k % (e - p); j > 0; j--) {
        s = s * (x + 1) % M;
        i++;
    }

    // A maradek elemek erteke 'x' lesz egeszen 'e-1'-ig. 
    for (; i < e; i++) {
        s = s * x % M;
    }

    // A vektor vegen pedig azok az elemek maradnak, amelyeket mar nem lehet
    // kipotolni, mert tolsagosan nagyok.
    for (; i < n; i++) {
        s = s * v[i] % M;
    }

    cout << s << '\n';
}

int main() {
    std::vector<int64_t> v;
    int k, b;
    beolvas(std::cin, v, k, b);

    feldolgoz(v, k, b);

    return 0;
}
RészfeladatÖsszpontTesztVerdiktIdőMemória
base40/50
1Elfogadva0/03ms356 KiB
2Elfogadva0/03ms524 KiB
3Elfogadva0/03ms356 KiB
4Elfogadva0/03ms416 KiB
5Elfogadva0/06ms668 KiB
6Elfogadva2/23ms496 KiB
7Elfogadva2/23ms384 KiB
8Elfogadva2/23ms548 KiB
9Elfogadva2/23ms356 KiB
10Elfogadva2/27ms632 KiB
11Elfogadva2/256ms2716 KiB
12Elfogadva1/159ms2788 KiB
13Elfogadva1/13ms504 KiB
14Elfogadva1/17ms484 KiB
15Futási hiba0/123ms1176 KiB
16Elfogadva1/125ms1052 KiB
17Futási hiba0/123ms1204 KiB
18Elfogadva1/113ms1252 KiB
19Futási hiba0/143ms1944 KiB
20Futási hiba0/132ms1636 KiB
21Futási hiba0/161ms2404 KiB
22Futási hiba0/127ms1508 KiB
23Elfogadva1/161ms2532 KiB
24Elfogadva1/159ms2916 KiB
25Elfogadva2/22ms356 KiB
26Elfogadva2/27ms616 KiB
27Futási hiba0/232ms1380 KiB
28Futási hiba0/132ms1380 KiB
29Elfogadva2/225ms1124 KiB
30Elfogadva1/161ms2280 KiB
31Futási hiba0/145ms2456 KiB
32Elfogadva2/23ms356 KiB
33Elfogadva2/261ms2276 KiB
34Elfogadva1/161ms2072 KiB
35Elfogadva2/261ms2276 KiB
36Elfogadva2/261ms2276 KiB
37Elfogadva2/261ms2276 KiB
38Elfogadva2/261ms2280 KiB
39Elfogadva1/13ms484 KiB