Cod sursa(job #1657533)

Utilizator SmarandaMaria Pandele Smaranda Data 20 martie 2016 16:09:14
Problema Cowfood Scor 18
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.87 kb
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 21, K = 31, S = 10032, MOD = 3210121;

int a [N][K], total = 0, A [K], lim, sp [S];
int dp [S];

int mypow (int a, int b) {
    int c = 1;

    for (;b; b >>= 1) {
        if (b & 1)
            c = 1ll * a * c % MOD;
        a = 1ll * a * a % MOD;
    }
    return c;
}

void preg (int n, int k) {
    int i;

    dp [k] = k;
    sp [k] = k;
    total = k;
    for (i = k + 1; i <= n; i ++) {
        dp [i] = (1ll * i * dp [i - 1]) % MOD * mypow (i - k + 1, MOD - 2) % MOD;
        sp [i] = (sp [i - 1] + dp [i]) % MOD;
        total = total + dp [i];
        while (total >= MOD)
            total -= MOD;
    }
}

void add (int k) {
    int i;

    for (i = 1; i <= lim; i ++)
        A [i] = max (A [i], a [k][i]);
}

int main () {
    int n, k, s, i, ns, sum, S, num, ans, j, v, b;

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

    scanf ("%d%d%d", &k, &s, &n);
    for (i = 1; i <= n; i ++)
        for (j = 1; j <= k; j ++)
            scanf ("%d", &a [i][j]);
    preg (s + k - 1, k);
    total = total - s * k;
    while (total < 0)
        total += MOD;
    ns = (1 << n) - 1;
    lim = k;
    for (v = 1; v <= ns; v ++) {
        num = 0;
        memset (A, 0, sizeof (A));
        for (b = 0; b < n; b ++)
            if (v & (1 << b)) {
                add (b + 1);
                num ++;
            }
        sum = 0;
        for (b = 1; b <= k; b ++)
            sum += A [b];
        S = s - sum;
        ans = 0;
        ans = sp [S + k - 1];
        if (num % 2 == 0)
            total = (total + ans) % MOD;
        else {
            total -= ans;
            while (total < 0)
                total += MOD;
        }
    }
    printf ("%d\n", total - n);
    return 0;
}