Pagini recente » Cod sursa (job #1980797) | Cod sursa (job #3309434) | Cod sursa (job #3352719) | Cod sursa (job #2037446) | Cod sursa (job #3340497)
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ifstream fin("cowfood.in");
ofstream fout("cowfood.out");
const int NMAX = 20;
const int KMAX = 30;
const int SMAX = 20000;
const int MOD = 3210121;
int k, s, n, answer;
int a[NMAX + 1][KMAX + 1];
int maxi[KMAX + 1];
int fact[SMAX + 50], invfact[SMAX + 50];
int power(int base, int exp) {
int res = 1;
while(exp) {
if(exp % 2 == 1) res = (ll)res * base % MOD;
base = (ll)base * base % MOD;
exp /= 2;
}
return res;
}
int combinari(int nn, int kk) {
if(nn < 0 || kk < 0 || kk > nn) return 0;
return (ll)fact[nn] * invfact[kk] % MOD * invfact[nn - kk] % MOD;
}
int main() {
fin >> k >> s >> n;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= k; j++) {
fin >> a[i][j];
}
}
fact[0] = 1;
// We need combinations up to S + K
int max_fact = s + k + 5;
for(int i = 1; i <= max_fact; i++) {
fact[i] = (ll)fact[i - 1] * i % MOD;
}
invfact[max_fact] = power(fact[max_fact], MOD - 2);
for(int i = max_fact - 1; i >= 0; i--) {
invfact[i] = (ll)invfact[i + 1] * (i + 1) % MOD;
}
answer = 0;
// Start mask from 0 to include the base case
for(int mask = 0; mask < (1 << n); mask++) {
fill(maxi + 1, maxi + k + 1, 0); // Corrected to 0
for(int i = 1; i <= n; i++) {
if((mask >> (i - 1)) & 1) {
for(int j = 1; j <= k; j++) {
maxi[j] = max(maxi[j], a[i][j]);
}
}
}
int sum_here = 0;
for(int j = 1; j <= k; j++) {
sum_here += maxi[j];
}
// Must prevent negative parameters in combinari
if(sum_here <= s) {
int ways = combinari(s - sum_here + k, k); // Fixed to 'k'
int sign = (__builtin_popcount(mask) % 2 == 1 ? -1 : 1);
answer = ((ll)answer + sign * ways % MOD + MOD) % MOD;
}
}
// --- SUBTRACT INVALID MIXTURES (< 2 non-zero quantities) ---
// 1. Check the mixture with exactly 0 quantities (all 0s)
bool ok0 = true;
for(int i = 1; i <= n; i++) {
bool all_zero = true;
for(int j = 1; j <= k; j++) {
if(a[i][j] > 0) all_zero = false;
}
if(all_zero) { ok0 = false; break; } // Banned by this experiment
}
if(ok0) answer = (answer - 1 + MOD) % MOD;
// 2. Check mixtures with exactly 1 non-zero quantity
for(int j = 1; j <= k; j++) {
int limit = s; // Maximum valid amount for herb j
for(int i = 1; i <= n; i++) {
bool strict_others = true;
for(int m = 1; m <= k; m++) {
if(m != j && a[i][m] > 0) strict_others = false;
}
// If the failed experiment only relies on herb j, it caps our limit
if(strict_others) {
limit = min(limit, a[i][j] - 1);
}
}
if(limit > 0) {
answer = (answer - limit + MOD) % MOD;
}
}
fout << answer << '\n';
return 0;
}