Cod sursa(job #3144975)

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

using namespace std;

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

void maxSelf(short int &x, short 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<short int>> v(n, vector<short 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);
	});
	map<int, vector<short int>> r;
	r[0] = vector<short int>(k, 0);
	int pos = 0;
	for(const int &mask: masks) {
		// while(!r.empty() && __builtin_popcount(r.begin()->first) < __builtin_popcount(mask) - 1) {
		// 	r.erase(r.begin());
		// }
		r[mask] = r[mask - lsb(mask)];
		for(int i = 0; i < k; i++) {
			maxSelf(r[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;
}