Cod sursa(job #2291798)

Utilizator BogdanisarBurcea Bogdan Madalin Bogdanisar Data 28 noiembrie 2018 17:31:00
Problema Cowfood Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.3 kb
#include <bits/stdc++.h>

using namespace std;

#if 1
    #define pv(x) std::cout<<#x<<" = "<<(x)<<"; ";std::cout.flush()
    #define pn std::cout<<endl
#else
    #define pv(x)
    #define pn
#endif

#ifdef INFOARENA
    ifstream in("cowfood.in");
    ofstream out("cowfood.out");
#else
    #define in cin
    #define out cout
#endif

using ll = long long;
using ull = unsigned long long;
using uint = unsigned int;
using ld = long double;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using pld = pair<ld, ld>;
#define pb push_back
const double PI = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862;
const int inf_int = 2e9 + 5;
const ll inf_ll = 1e18 + 5;
const int SMax = 1e4 + 5;
const int NMax = 20 + 5;
const int KMax = 30 + 5;
const int mod = 3210121;
const int dx[] = {-1,0,0,+1}, dy[] = {0,-1,+1,0};

int N, K, S, badMixtures;
int pcomb[SMax + KMax], fact[SMax + KMax];
int mixture[NMax][KMax], maxs[NMax][KMax];

int pw(int base, int exp) {
    int ans = 1;
    while (exp) {
        if (exp & 1) {
            ans = (1LL * ans * base) % mod;
        }
        base = (1LL * base * base) % mod;
        exp >>= 1;
    }

    return ans;
}

void bkt(int idx, int totalChosen) {
    if (idx == N + 1) {
        if (totalChosen == 0) {
            return;
        }

        int sum = 0;
        for (int i = 1; i <= K; ++i) {
            sum += maxs[N][i];
        }

        int numHere;
        if (sum > S) {
            numHere = 0;
        }
        else {
            int dif = S - sum;
            numHere = (pcomb[dif + K - 1] - pcomb[(K - 1) - 1] + mod) % mod;
        }
        if (totalChosen % 2 == 0) {
            numHere *= -1;
        }

        badMixtures = (badMixtures + numHere + mod) % mod;
        return;
    }

    for (int j = 1; j <= K; ++j) {
        maxs[idx][j] = maxs[idx-1][j];
    }
    bkt(idx + 1, totalChosen);

    for (int j = 1; j <= K; ++j) {
        maxs[idx][j] = max(maxs[idx-1][j], mixture[idx][j]);
    }
    bkt(idx + 1, totalChosen + 1);
}

int main() {
    cin.sync_with_stdio(false);
    cin.tie(0);

    in >> K >> S >> N;

    fact[0] = 1;
    for (int i = 1; i <= S + K - 1; ++i) {
        fact[i] = (1LL * fact[i-1] * i) % mod;
    }

    for (int i = 1; i <= S + K - 1; ++i) {
        int comb;
        if (K-1 <= i) {
            comb = (1LL * fact[i] * pw( 1LL * fact[i - (K - 1)] * fact[K - 1] % mod, mod - 2 )) % mod;
        }
        else {
            comb = 0;
        }

        pcomb[i] = (pcomb[i-1] + comb) % mod;
    }

    for (int i = 1; i <= N; ++i) {
        for (int j = 1; j <= K; ++j) {
            in >> mixture[i][j];
        }
    }

    vector<int> maxs(K + 1);
    bkt(1, 0);

    int totalMixtures = 0;
    // for (int sum = 2; sum <= S; ++sum) {
    //     totalMixtures += comb[sum + K - 1][K - 1];
    //     totalMixtures %= mod;
    //     totalMixtures = (totalMixtures - K + mod) % mod;
    // }

    // formula rezulta din for-ul de sus;
    totalMixtures = (pcomb[S + K - 1] - pcomb[(2 + K - 1) - 1] + mod) % mod;
    totalMixtures = (totalMixtures - (S - 2 + 1) * K + mod) % mod;

    int goodMixtures = (totalMixtures - badMixtures + mod) % mod;
    out << goodMixtures << '\n';
    
    return 0;
}