Cod sursa(job #1480078)

Utilizator toranagahVlad Badelita toranagah Data 2 septembrie 2015 01:35:24
Problema Cowfood Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.04 kb
//Problem cowfood from Infoarena
#include <cmath>

#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

#ifndef BOSS_MAXIM
    ifstream fin("cowfood.in");
    tofstream fout("cowfood.out");
#else
    #define fin cin
    #define fout cout
#endif

const int INF = 1 << 30;
const int MOD = 3210121;
const int MAX_N = 25;
const int MAX_K = 35;
const int MAX_S = 10100;

int K, S, N;
int fact[MAX_S];
int inv_fact[MAX_S];
int a[MAX_N][MAX_S];
int f[MAX_S];
int mx[MAX_N][MAX_K];
int ans = 0;

void backtrack(int step, int sign);
int log_pow(int n, int p);
int mod(long long n);
int comb(int n, int k);

int main() {
  fin >> K >> S >> N;
  for (int i = 1; i <= N; i += 1)
    for (int j = 1; j <= K; j += 1)
      fin >> a[i][j];

  fact[0] = inv_fact[0] = 1;
  for (int i = 1; i <= S + K; i += 1) {
    fact[i] = mod(1LL * fact[i - 1] * i);
  }

  inv_fact[S + K] = log_pow(fact[S + K], MOD - 2);
  for (int i = S + K - 1; i > 0; i -= 1)
    inv_fact[i] = mod(1LL * inv_fact[i + 1] * (i + 1));

  for (int i = 0; i <= S; i += 1) {
    f[i] = comb(i + K - 1, K - 1);
    if (i > 0)
      f[i] = mod(f[i] + f[i - 1]);
  }

  backtrack(1, 1);
  ans = mod(ans - (K * S + 1));
  fout << ans;
  return 0;
}

void backtrack(int step, int sign) {
  if (step > N) {
    int sum = 0;
    for (int i = 1; i <= K; i += 1)
      sum += mx[step - 1][i];
    if (sum <= S) ans = mod(ans + f[S - sum] * sign);
    return;
  }

  for (int i = 1; i <= K; i += 1)
    mx[step][i] = mx[step - 1][i];
  backtrack(step + 1, sign);

  for (int i = 1; i <= K; i += 1)
    mx[step][i] = max(mx[step - 1][i], a[step][i]);
  backtrack(step + 1, sign * -1);
}

inline int log_pow(int n, int p) {
  int res = 1;
  for (; p; p >>= 1) {
    if (p & 1)
      res = mod(1LL * res * n);
    n = mod(1LL * n * n);
  }
  return res;
}

inline int comb(int n, int k) {
  return mod(1LL * fact[n] * inv_fact[k] * inv_fact[n - k]);
}

inline int mod(int n) {
  while (n < 0) n += MOD;
  if (n < MOD) return n;
  if (n < 2 * MOD) return n - MOD;
  return n % MOD;
}