Cod sursa(job #3338461)

Utilizator GliggyGligor Andrei Gliggy Data 3 februarie 2026 15:19:08
Problema Cowfood Scor 38
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.09 kb
#include <bits/stdc++.h>
using namespace std;

static const int MOD = 3210121;

int add(int a, int b) {
    a += b;
    if (a >= MOD) a -= MOD;
    return a;
}

int sub(int a, int b) {
    a -= b;
    if (a < 0) a += MOD;
    return a;
}

int mul(long long a, long long b) {
    return (int)(a * b % MOD);
}

int main() {
    freopen("cowfood.in", "r", stdin);
    freopen("cowfood.out", "w", stdout);

    int K, S, N;
    cin >> K >> S >> N;

    vector<vector<int>> bad(N, vector<int>(K));
    for (int i = 0; i < N; i++)
        for (int j = 0; j < K; j++)
            cin >> bad[i][j];

    // Binomial coefficients
    int MAXN = S + K;
    vector<vector<int>> C(MAXN + 1, vector<int>(K + 1, 0));
    for (int n = 0; n <= MAXN; n++) {
        C[n][0] = 1;
        for (int k = 1; k <= min(n, K); k++)
            C[n][k] = add(C[n - 1][k - 1], C[n - 1][k]);
    }

    auto count_leq_sum = [&](int lim) {
        if (lim < 0) return 0;
        return C[lim + K][K];
    };

    // Total mixtures
    int total = count_leq_sum(S);
    total = sub(total, 1);          // zero vector
    total = sub(total, mul(K, S));  // exactly one nonzero

    int invalid = 0;
    int M = 1 << N;

    vector<int> cur(K);

    for (int mask = 1; mask < M; mask++) {
        int lsb = mask & -mask;
        int id = __builtin_ctz(lsb);
        int prev = mask ^ lsb;

        // rebuild max vector for this mask
        if (prev == 0) {
            cur = bad[id];
        } else {
            int p = prev;
            int pid = __builtin_ctz(lsb);
            for (int j = 0; j < K; j++)
                cur[j] = max(cur[j], bad[pid][j]);
        }

        int sum = 0;
        for (int j = 0; j < K; j++) {
            sum += cur[j];
            if (sum > S) break;
        }
        if (sum > S) continue;

        int ways = count_leq_sum(S - sum);
        if (__builtin_popcount(mask) & 1)
            invalid = add(invalid, ways);
        else
            invalid = sub(invalid, ways);
    }

    cout << sub(total, invalid) << "\n";
    return 0;
}