Cod sursa(job #3223099)

Utilizator SSKMFSS KMF SSKMF Data 12 aprilie 2024 13:43:55
Problema Cowfood Scor 18
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.99 kb
#include <fstream>
using namespace std;

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

const int mod(3210121);
int factorial[10021] , invers_factorial[10021];
int lungime , suma , numar_experimente;

inline int Exponentiere (int baza , int exponent)
{
    int rezultat = 1;
    for ( ; exponent ; exponent >>= 1 , baza = (int64_t)baza * baza % mod)
        { if (exponent & 1) { rezultat = (int64_t)rezultat * baza % mod; } }

    return rezultat;
}

inline int Combinari (const int total , const int luate)
{
    return total < 0 || luate < 0 || total < luate ? 0 : (int64_t)factorial[total] * invers_factorial[luate] % mod * invers_factorial[total - luate] % mod;
}

struct Experiment {
    int cantitate[32] = { } , total = 0;
    Experiment &operator += (const Experiment termen)
    {
        (*this).total = 0;
        for (int indice = 1 ; indice <= lungime ; indice++)
            { (*this).total += ((*this).cantitate[indice] = max((*this).cantitate[indice] , termen.cantitate[indice])); }

        return *this;
    }
    int Get () 
    { 
        if (suma < (*this).total)
            { return 0; }

        int modalitati = Combinari(suma - (*this).total + lungime , lungime) + ((*this).total == 0 ? 1 : 0) , stanga = 0 , dreapta = (*this).total; 
        for (int indice = 1 ; indice <= lungime ; indice++)
        {
            dreapta -= (*this).cantitate[indice];
            if (!stanga && !dreapta)
                { (modalitati += mod - (suma - (*this).cantitate[indice] + 1)) %= mod; }

            stanga += (*this).cantitate[indice];
        }

        return modalitati;
    }
} sir[21] , termen[1048576];

int setati[1048576];

int main ()
{   
    factorial[0] = 1;
    for (int valoare = 1 ; valoare <= 10020 ; valoare++)
        { factorial[valoare] = (int64_t)factorial[valoare - 1] * valoare % mod; }

    invers_factorial[10020] = Exponentiere(factorial[10020] , mod - 2);
    for (int valoare = 10019 ; valoare >= 0 ; valoare--)
        { invers_factorial[valoare] = (int64_t)invers_factorial[valoare + 1] * (valoare + 1) % mod; }

    cin >> lungime >> suma >> numar_experimente;

    for (int indice = 1 ; indice <= numar_experimente ; indice++) {
        for (int _indice = 1 ; _indice <= lungime ; _indice++)
            { cin >> sir[indice].cantitate[_indice]; sir[indice].total += sir[indice].cantitate[_indice]; }
    }

    int ramas = termen[0].Get();
    for (int masca = 1 , limita = (1 << numar_experimente) ; masca < limita ; masca++)
    {
        int indice = 1 , putere = 1;
        while (!(masca & putere))
            { indice++; putere <<= 1; }

        setati[masca] = setati[masca ^ putere] + 1;
        termen[masca] = termen[masca ^ putere];
        termen[masca] += sir[indice];
        
        if (!(setati[masca] & 1)) { (ramas += termen[masca].Get()) %= mod; }
        else { (ramas += mod - termen[masca].Get()) %= mod; }
    }

    cout << ramas;
    cout.close(); cin.close();
    return 0;
}