Cod sursa(job #2239413)

Utilizator LucaSeriSeritan Luca LucaSeri Data 10 septembrie 2018 18:13:30
Problema Cowfood Scor 54
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.26 kb
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <fstream>
using namespace std;

typedef pair< int, int > pii;
typedef pair< long long, long long > pll;
typedef long long ll;
typedef vector< int > vi;
typedef vector< ll > vll;
typedef vector< pii > vpii;
typedef long double ld;

ll lgput(ll a, ll b, ll mod) {
    ll ret = 1;
    while( b ){
        if(b & 1) ret = (ret * a) % mod;
        a = (a * a) % mod;
        b >>= 1;
    }

    return ret;
}

int binarySearch(vector< int > &v, int value) {
    int best = 0;
    for(int step = 29; step >= 0; --step) {
        if(best + (1<<step) < v.size() && v[best + (1<<step)] <= value) best += (1<<step);
    }

    return best;
}

const int MOD = 3210121;

const int MAXS = 1e4 + 50;
const int MAXN = 22;
const int MAXK = 33;

int comb[MAXS];
int k, s, n;
int recipes[MAXK][MAXN];
int logg[(1<<MAXN)];
int suma[(1<<MAXN)];
int maxim[(1<<MAXN)];

int main() {
    ios::sync_with_stdio(false);

    FILE *f = fopen("cowfood.in", "r");
    FILE *g = fopen("cowfood.out", "w");

    fscanf(f, "%i%i%i", &k, &s, &n);

    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < k; ++j) {
            fscanf(f, "%i", &recipes[j][i]);
        }
    }

    for(int i = 0; i < MAXS; ++i) comb[i] = 1;
    for(int i = 0; i < k; ++i) {
        for(int j = 0; j < MAXS; ++j) {
            comb[j] = (comb[j] + comb[j-1]);
            if(comb[j] >= MOD) comb[j] -= MOD;
        }
    }

    for(int i = 2; i <= (1<<n); ++i) {
        logg[i] = logg[i>>1] + 1;
    }

    int ans = comb[s];
    int lim = (1<<n);

    for(int i = 0; i < k; ++i) {
        memset(maxim, 0, sizeof maxim);
        for(int mask = 1; mask < lim; ++mask) {
            maxim[mask] = max(maxim[mask-(mask&-mask)], recipes[i][logg[mask&-mask]]);
            suma[mask] += maxim[mask];
        }
    }

    for(int mask = 1; mask < lim; ++mask) {
        if(__builtin_popcount(mask)&1) ans = (ans + MOD - comb[s - suma[mask]]);
        else ans = (ans + comb[s-suma[mask]]);

        if(ans >= MOD) ans -= MOD;
    }

    ///Scadem pe cele care nu au macar 2 nenule
    fprintf(g, "%i\n", (ans + (MOD - s*k - 1)) % MOD);
    fclose(f);
    fclose(g);
    return 0;
}