Cod sursa(job #2240396)

Utilizator oldatlantianSerban Cercelescu oldatlantian Data 13 septembrie 2018 10:53:44
Problema Pod Scor 95
Compilator cpp Status done
Runda simulare_prega Marime 2.31 kb
#include <algorithm>
#include <fstream>
#include <cstring>
using namespace std;

ifstream fi("pod.in");
ofstream fo("pod.out");

const int N = 1e9 + 5, M = 1005, K = 25, MOD = 9901;

int n, m, k;
int planks[M], plank[K], trans[K][K], resmx[K][K], tempmx[K][K], pow2mx[K][K];

static void update_plank() {
	static int new_plank[K];
	memset(new_plank, 0x00, sizeof new_plank);
	for (int i = 0; i <= k; ++i)
	for (int j = 0; j <= k; ++j)
		new_plank[i]+= resmx[i][j] * plank[j];
	for (int i = 0; i <= k; ++i)
		new_plank[i]%= MOD;
	memcpy(plank, new_plank, sizeof plank); }

static void mult() {
	memset(tempmx, 0x00, sizeof tempmx);
	for (int i = 0; i <= k; ++i)
	for (int j = 0; j <= k; ++j)
	for (int p = 0; p <= k; ++p)
		tempmx[i][j] = (tempmx[i][j] + resmx[i][p] * pow2mx[p][j]);
	for (int i = 0; i <= k; ++i)
	for (int j = 0; j <= k; ++j)
		tempmx[i][j]%= MOD;
	memcpy(resmx, tempmx, sizeof tempmx); }

static void square() {
	memset(tempmx, 0x00, sizeof tempmx);
	for (int i = 0; i <= k; ++i)
	for (int j = 0; j <= k; ++j)
	for (int p = 0; p <= k; ++p)
		tempmx[i][j] = (pow2mx[i][p] * pow2mx[p][j] + tempmx[i][j]);
	for (int i = 0; i <= k; ++i)
	for (int j = 0; j <= k; ++j)
		tempmx[i][j]%= MOD;

	memcpy(pow2mx, tempmx, sizeof tempmx); }

static void update_matrix(int pwr) {
	memcpy(pow2mx, trans, sizeof trans);
	for (int i = 0; i <= k; ++i)
	for (int j = 0; j <= k; ++j)
		resmx[i][j] = int(i == j);

	for (int lg = 0; (1 << lg) <= pwr; ++lg) {
		if (pwr & (1 << lg))
			mult();
		square(); } }

int main() {
	int lim, ptr = 0;

	fi >> n >> m >> k;
	for (int i = 0; i < m; ++i)
		fi >> planks[i];
	sort(planks, planks + m);
	for (int i = m; i < M; ++i)
		planks[i] = n + 1;

	for (int i = 0; i < k; ++i) { // init plank
		if (planks[ptr] == i) {
			ptr++;
			break; }
		plank[i] = 1; }

	while (planks[ptr] <= k)
		++ptr;
	if (k == 0 || planks[k - 1] != k)
		plank[k] = plank[k - 1] + plank[0];

	if (k == 1) {
		fo << (m == 0 ? 1 : 0) << endl;
		return 0; }
	if (n <= k) {
		fo << plank[n] << endl;
		return 0; }

	for (int i = 0; i < k; ++i) // init trans matrix
		trans[i][i + 1] = 1;
	trans[k][1] = trans[k][k] = 1;
	lim = k;

	do {
		update_matrix(planks[ptr] - lim - 1);
		update_plank();
		lim = planks[ptr++];
		for (int i = 0; i < k; ++i)
			plank[i] = plank[i + 1];
		plank[k] = 0; }
	while (ptr <= m);

	fo << plank[k - 1] << endl;

	return 0; }