Submission #1277787

#TimeUsernameProblemLanguageResultExecution timeMemory
1277787alahunovahmadBank (IZhO14_bank)C++20
71 / 100
1093 ms8648 KiB
#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int N, M;
    if (!(cin >> N >> M)) return 0;
    vector<int> a(N), b(M);
    long long sumA = 0, sumB = 0;
    for (int i = 0; i < N; ++i) { cin >> a[i]; sumA += a[i]; }
    for (int j = 0; j < M; ++j) { cin >> b[j]; sumB += b[j]; }

    // Быстрая невозможность: если сумма банкнот меньше суммы зарплат -> NO
    if (sumB < sumA) {
        cout << "NO\n";
        return 0;
    }

    // Сортируем зарплаты по убыванию (улучшает ранний отсев в DP)
    sort(a.rbegin(), a.rend());

    int FULL = 1 << M;
    // Предвычисляем суммы подмножеств банкнот
    vector<int> sum(FULL, 0);
    for (int mask = 1; mask < FULL; ++mask) {
        int lowbit = mask & -mask;
        int pos = __builtin_ctz(lowbit); // позиция добавленного бита
        sum[mask] = sum[mask ^ lowbit] + b[pos];
    }

    // dp[mask] = максимальное число людей, которых можно полностью оплатить, используя банкноты из mask
    // Изначально -1 (недостижимо), dp[0] = 0
    vector<int> dp(FULL, -1);
    dp[0] = 0;

    for (int mask = 0; mask < FULL; ++mask) {
        if (dp[mask] < 0) continue;
        if (dp[mask] == N) break; // уже оплатили всех
        int need = a[dp[mask]]; // платим (dp[mask])-ому человеку -> требуется сумма need
        int remaining = ((FULL - 1) ^ mask); // банкноты, которые ещё не использованы

        // Перебираем все непустые подмножества remaining
        // sub перебирается снизу вверх: sub = remaining; sub = (sub-1) & remaining; ...
        for (int sub = remaining; sub; sub = (sub - 1) & remaining) {
            if (sum[sub] == need) {
                int nmask = mask | sub;
                if (dp[nmask] < dp[mask] + 1) {
                    dp[nmask] = dp[mask] + 1;
                }
            }
        }
    }

    // Если есть такой mask, что dp[mask] == N -> YES, иначе NO
    bool ok = false;
    for (int mask = 0; mask < FULL; ++mask) {
        if (dp[mask] == N) { ok = true; break; }
    }

    cout << (ok ? "YES\n" : "NO\n");
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...