Cod sursa(job #1756682)

Utilizator Y.MalmsteenB.P.M. Y.Malmsteen Data 13 septembrie 2016 14:02:15
Problema Cowfood Scor 18
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.32 kb
#include <iostream>
#include <fstream>
using namespace std;

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

const int NMAX = 21, KMAX = 31, SMAX = 100001;
const int MOD = 3210121;

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

/*
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)
{
    int x1 = 0, y1 = 1;
    x = 1, y = 0;
    while(b != 0)
    {
        int q = a / b;
        int r = a % b;
        a = b;
        b = r;
        int x0 = x - x1 * q;
        int y0 = y - y1 * q;
        x = x1;
        y = y1;
        x1 = x0;
        y1 = y0;
    }
    d = a;
}

/*
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;
    }
}

void maxV(int A[], int B[], int C[])
{
    for(int i = 1; i <= K; i++)
        C[i] = max(A[i], B[i]);
}

void genSubm(int n, int m)
{
    int semn, k = 1;
    x[1] = 0;
    if(m % 2 == 0) semn = -1;
    else semn = 1;
    while(k > 0)
        if(x[k] < n - m + k)
        {
            x[k]++;
            maxV(MAX[k - 1], M[k], MAX[k]);
            if(k == m)
            {
                int D = S;
                for(int i = 1; i <= K; i++)
                    D -= MAX[m][i];
                E += semn * SCOMB[D];
                E %= MOD;
            }
            else
            {
                k++;
                x[k] = x[k - 1];
            }
        }
        else
            k--;
}
int main()
{
    f >> K >> S >> N;
    calcSumComb();
    for(int i = 1; i <= N; i++)
        for(int j = 1; j <= K; j++)
            f >> M[i][j];
    E = 0;
    for(int i = 1; i <= N; i++)
        genSubm(N, i);
    V = (SCOMB[S] - S * K - E - 1) % MOD;
    if(V < 0)V += MOD;
    g << V;
    return 0;
}