Cod sursa(job #3219841)

Utilizator ezluciPirtac Eduard ezluci Data 1 aprilie 2024 15:57:27
Problema Cowfood Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.17 kb
#pragma GCC optimize("Ofast,unroll-loops")
using namespace std;
#ifdef EZ
   #include "./ez/ez.h"
   const string FILE_NAME = "test";
#else
   #include <bits/stdc++.h>
   const string FILE_NAME = "cowfood";
#endif
#define mp make_pair
#define ll long long
#define pb push_back
#define fi first
#define se second
#define cin fin
#define cout fout
ifstream fin (FILE_NAME + ".in");
ofstream fout (FILE_NAME + ".out");

const int MOD = 3210121;

int k, s, n;

int fact[10101];
int factInv[10101];

void euclid(int a, int b, int &x, int &y)
{
   if (b == 0) return (void) (x = y = 1);

   int x0, y0;
   euclid(b, a%b, x0, y0);
   x = y0;
   y = x0 - a/b*y0;
}

void genFact()
{
   fact[0] = factInv[0] = 1;
   int tmp;
   for (int i = 1; i < 10101; ++i)
   {
      fact[i] = 1LL * fact[i-1] * i % MOD;
      euclid(fact[i], MOD, factInv[i], tmp);
      if (factInv[i] < 0)  factInv[i] += MOD;
   }
}


// sum_{h=0..lim} comb(k-1+h, h)
int cool[10101];
void genCool()
{
   for (int i = 1; i + k-1 < 10101; ++i)
      cool[i] = (cool[i-1] + 1LL * fact[i + k-1 - 1] * factInv[i-1] % MOD) % MOD;
}

inline int coolComb(int lim)
{
   return 1LL * factInv[k-1] * cool[lim+1] % MOD;
}


int main()
{
   genFact();

   cin >> k >> s >> n;
   genCool();
   int v[20][30];
   for (int i = 0; i < n; ++i)
      for (int j = 0; j < k; ++j)  cin >> v[i][j];
   
   for (int i = 0; i < n; ++i)
   {
      int lib = 0;
      for (int j = 0; j < k; ++j)
         if (v[i][j])   lib++;
      
      if (lib <= 1)  cout << 0,  exit(0);
   }

   
   int ANS = (coolComb(s) - 1 - s*k) % MOD;
   if (ANS < 0)   ANS += MOD;

   int conf[30];
   for (int msk = 1; msk < (1<<n); ++msk)
   {
      memset(conf, 0, 4*k);
      for (int i = 0; i < n; ++i)
         if (msk & 1<<i)
            for (int j = 0; j < k; ++j)
               conf[j] = max(conf[j], v[i][j]);
      
      int sc = 0;
      for (int j = 0; j < k; ++j)
         sc += conf[j];
      
      if (sc > s) continue;
      
      int ans = coolComb(s-sc);
      
      if (__builtin_popcount(msk) & 1)
      {
         ANS -= ans;
         if (ANS < 0)   ANS += MOD;
      }
      else
      {
         ANS += ans;
         if (ANS >= MOD) ANS -= MOD;
      }
   }

   cout << ANS;
}