Cod sursa(job #2215753)

Utilizator ContDeRacistAliniateEBlat ContDeRacist Data 23 iunie 2018 16:31:40
Problema Cowfood Scor 98
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.39 kb
#include <fstream>

using namespace std;

ifstream cin("cowfood.in");
ofstream cout("cowfood.out");

const int S = 1e4 + 9, N = 2e1, K = 3e1, MOD = 3210121;

short int ansmax[K], v[N][K], lim[K];

int starsb[S], fact[S], invf[S];

int k, s;

int ans(0);

int logpow(int base, int exp) {
    int ans(1), cur(base);
    while (exp) {
        if (exp&1) {
            ans = 1LL * cur * ans % MOD;
        }
        cur = 1LL * cur * cur % MOD;
        exp>>=1;
    }
    return ans;
}

void prec() {
    fact[0] = 1;
    for (int i = 1; i <= s; ++i) {
        fact[i] = 1LL * fact[i - 1] * i % MOD;
    }
    invf[s] = logpow(fact[s], MOD - 2);
    invf[0] = 1;
    for (int i = s - 1; i > 0; --i) {
        invf[i] = 1LL * invf[i + 1] * (i + 1) % MOD;
    }
    starsb[0] = 1;
    int alpha = 1;
    for (int i = 1; i <= s; ++i) {
        alpha = 1LL * alpha * (k + i - 1) % MOD;
        starsb[i] = 1LL * alpha * invf[i] % MOD + starsb[i - 1];
        if (starsb[i] >= MOD) {
            starsb[i] -= MOD;
        }
    }
}

void bkt(bool par, int poz) {
    int sum(0);
    short int copieans[30];
    for (int i = 0; i < k; ++i) {
        sum += ansmax[i];
        copieans[i] = ansmax[i];
    }
    if (sum > s) {
        return;
    }
    if (par) {
        ans += starsb[s - sum];
        if (ans >= MOD) {
            ans -= MOD;
        }
    }
    else {
        ans -= starsb[s - sum];
        if (ans < 0) {
            ans += MOD;
        }
    }
    for (int i = poz - 1; i >= 0; --i) {
        for (int j = 0; j < k; ++j) {
            ansmax[j] = max(copieans[j], v[i][j]);
        }
        bkt(1 - par, i);
    }
}

int main()
{
    int n;
    cin >> k >> s >> n;
    prec();
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < k; ++j) {
            cin >> v[i][j];
        }
    }
    bkt(1, n);
    ans--;
    if (ans < 0) {
        ans += MOD;
    }
    for (int i = 0; i < k; ++i) {
        lim[i] = s;
    }
    for(int i = 0; i < n; ++i) {
        int lol(0), poz(0);
        for (int j = 0; j < k; ++j) {
            if (v[i][j] > 0) {
                ++lol;
                poz = j;
            }
        }
        if (lol == 1) {
            lim[poz] = min(lim[poz], v[i][poz]);
        }
    }
    for (int i = 0; i < k; ++i) {
        ans -= lim[i];
    }
    cout << ans << "\n";
    return 0;
}