Cod sursa(job #2845384)

Utilizator StefanSanStanescu Stefan StefanSan Data 7 februarie 2022 19:20:00
Problema Cowfood Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.38 kb
#include <iostream>
#include <fstream>

using namespace std;
const int  MOD = 3210121,
NMAX = 21,
KMAX = 31,
SMAX = 10001;

int K, S, N, V, E;
int M[NMAX][KMAX], x[NMAX], MAX[NMAX][KMAX], SCOMB[SMAX];

ifstream f("cowfood.in");
ofstream g("cowfood.out");

/**
Algoritmul extins al lui Euclid.
Se determina d=cmmdc(a,b) si doua numere intregi x si y,
astfel incat
          a * x + b * y = d.
*/
void EuclidExtins(int a, int b, int& d, int& x, int& y) //Varianta recursiva
{
    if (b == 0)
    {
        x = 1;
        y = 1;
        d = a;
    }
    else
    {
        int x0, y0;
        EuclidExtins(b, a % b, d, x0, y0);
        x = y0;
        y = x0 - (a / b) * y0;
    }
}

/**
Se determina inversul modular (modulo MOD) al numarului a,
adica un numar x astfel incat a * x sa fie congruent cu 1,
modulo MOD.
*/
int inversMod(int a)
{
    int d, x, y;
    EuclidExtins(a, MOD, d, x, y);
    x %= MOD;
    if (x < 0) x += MOD;
    return x;
}

void calcSumComb()
{
    long long c = 1;
    SCOMB[0] = 1;
    for (int i = 1; i <= S; i++)
    {
        c *= i + K - 1;
        c %= MOD;
        c *= inversMod(i);
        c %= MOD;
        SCOMB[i] = SCOMB[i - 1] + c;
        SCOMB[i] %= MOD;
    }
}

void genSubm(int n, int m)
{
    int semn, k = 1, i;
    x[1] = 0;
    if (m % 2 == 0) semn = -1;
    else semn = 1;
    while (k > 0)
        if (x[k] < n - m + k)
        {
            x[k]++;
            for (i = 1; i <= K; i++)
                MAX[k][i] = max(MAX[k - 1][i], M[x[k]][i]);
            if (k == m)
            {
                int sum = 0;
                for (i = 1; i <= K; i++)
                    sum += MAX[m][i];
                if (sum <= S)
                {
                    E += MOD + semn * SCOMB[S - sum];
                    E %= MOD;
                }
            }
            else
            {
                k++;
                x[k] = x[k - 1];
            }
        }
        else
            k--;
}

int main()
{
    f >> K >> S >> N;
    for (int i = 1; i <= N; i++)
        for (int j = 1; j <= K; j++)
            f >> M[i][j];
    calcSumComb();
    ///E = 0;
    for (int i = 1; i <= N; i++)
        genSubm(N, i);
    V = SCOMB[S] + (MOD - S * K - 1);
    V %= MOD;
    V += MOD - E;
    V %= MOD;
    g << V;
    f.close();
    g.close();
    return 0;
}