Cod sursa(job #3144971)

Utilizator andrei_C1Andrei Chertes andrei_C1 Data 11 august 2023 16:44:05
Problema Cowfood Scor 54
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.01 kb
#include <bits/stdc++.h>

using namespace std;

ifstream fin("cowfood.in");
ofstream fout("cowfood.out");

void maxSelf(int &x, int y) {
	if(y > x) {
		x = y;
	}
}

const int MOD = 3210121;

void addSelf(int &x, int y) {
	x += y;
	if(x >= MOD) {
		x -= MOD;
	}
	if(x < 0) {
		x += MOD;
	}
}

int add(int x, int y) {
	addSelf(x, y);
	return x;
}

void multSelf(int &x, int y) {
	x = (long long) x * y % MOD;
}

int mult(int x, int y) {
	multSelf(x, y);
	return x;
}

int fact(int n) {
	static vector<int> data(1, 1);
	for(int i = data.size(); i <= n; i++) {
		data.emplace_back(mult(data[i - 1], i));
	}
	return data[n];
}

int inv(int n) {
	static vector<int> data(2, 1);
	for(int i = data.size(); i <= n; i++) {
		data.emplace_back(mult(data[MOD % i], MOD - MOD / i));
	}
	return data[n];
}

int ifact(int n) {
	static vector<int> data(2, 1);
	for(int i = data.size(); i <= n; i++) {
		data.emplace_back(mult(data[i - 1], inv(i)));
	}
	return data[n];
}

int comb(int n, int k) {
	return mult(fact(n), mult(ifact(k), ifact(n - k)));
}

int lsb(int mask) {
	return mask & (-mask);
}

int main() {
	int k, s, n;
	fin >> k >> s >> n;
	vector<vector<int>> v(n, vector<int>(k));
	for(auto &row: v) {
		for(auto &it: row) {
			fin >> it;
		}
	}
	int cnt = add(comb(s + k, k), -1 - k * s);
	vector<int> masks;
	for(int mask = 1; mask < (1 << n); mask++) {
		masks.emplace_back(mask);
	}
	sort(masks.begin(), masks.end(), [] (const int &a, const int &b) {
		return __builtin_popcount(a) < __builtin_popcount(b);
	});
	vector<vector<int>> r(masks.size() + 1, vector<int>(k));
	for(const int &mask: masks) {
		for(int i = 0; i < k; i++) {
			r[mask][i] = max(r[mask - lsb(mask)][i], v[__lg(lsb(mask))][i]);
		}
		int sum = 0, good = 0;
		for(int i = 0; i < k; i++) if(r[mask][i]) {
			good += 1;
			sum += r[mask][i];
		}
		int desired = s - sum;
		if(desired < 0 || good < 2) {
			continue;
		}
		if(__builtin_popcount(mask) & 1) {
			addSelf(cnt, -comb(desired + k, k));
		} else {
			addSelf(cnt, comb(desired + k, k));
		}
	}
	fout << cnt << '\n';
	return 0;
}