Cod sursa(job #466359)

Utilizator CezarMocanCezar Mocan CezarMocan Data 26 iunie 2010 13:14:47
Problema Pod Scor Ascuns
Compilator cpp Status done
Runda Marime 2.25 kb
#include <cstdio>
#include <cstring>
#include <algorithm>

#define maxM 1010
#define maxK 52
#define mod 9901

using namespace std;

int N, M, K;
int pos[maxM];
int line[maxK], line_ant[maxK], mat[maxK][maxK], rez[maxK][maxK];
int bad_erase[maxM], nr_erase;
bool bad[2 * maxK];

void afis(int mat[][maxK]) {
	int i, j;
	for (i = 0; i < K; i++) {
		for (j = 0; j < K; j++)
			printf("%d ", mat[i][j]);
		printf("\n");
	}
	printf("\n");
}

inline void mult(int A[][maxK], int B[][maxK], int C[][maxK]) {
	int i, j, k;

	for (i = 0; i < K; i++)
		for (k = 0; k < K; k++) 
			for (j = 0; j < K; j++)
				C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % mod;
}

void mat_pow(int power, int mat[][maxK], int rez[][maxK]) {
	int i;
	int matP2[maxK][maxK], aux[maxK][maxK];

	for (i = 0; i < K; i++)
		rez[i][i] = 1;

//	fprintf(stderr, "%d\n", power);
	memcpy(matP2, mat, sizeof(matP2));
	for (i = 0; (1 << i) <= power; i++) {
		if (power & (1 << i)) {
			memset(aux, 0, sizeof(aux));
			mult(rez, matP2, aux);
			memcpy(rez, aux, sizeof(aux));
		}

		memset(aux, 0, sizeof(aux));
		mult(matP2, matP2, aux);
		memcpy(matP2, aux, sizeof(matP2));
	}
}


int main() {
	int i, j;
	int i1, i2;

	freopen("grader_test7.in", "r", stdin);
	freopen("grader_test7.ok", "w", stdout);

	scanf("%d%d%d", &N, &M, &K);
	for (i = 1; i <= M; i++)
		scanf("%d", &pos[i]);

	sort(pos + 1, pos + M + 1);
	M++; pos[M] = N + 1;

	mat[K - 1][0] = 1; mat[K - 1][K - 1] = 1;
	for (i = 1; i < K; i++) 
		mat[i - 1][i] = 1;

	i1 = 0;
	while (i1 < M) {
		i2 = i1;

		nr_erase = 0;
		while (pos[i2] - pos[i1] < K && i2 <= M) {
			bad[pos[i2] - pos[i1]] = 1;
			nr_erase++;
			bad_erase[nr_erase] = pos[i2] - pos[i1];
			i2++;
		}

		if (i1 == 0) line[0] = 1;
		else line[0] = 0;

		for (i = 1; i < K; i++) {
			if (bad[i]) line[i] = 0;
			else line[i] = (line[i - 1] + line_ant[i]) % mod;
		}

		if (pos[i2] - pos[i1] - K < 0) {
			printf("%d\n", line[N - pos[i1]]);
			return 0;
		}

		memset(rez, 0, sizeof(rez));
		memset(line_ant, 0, sizeof(line_ant));
		mat_pow(pos[i2] - pos[i1] - K, mat, rez);

		for (i = 0; i < K; i++)
			for (j = 0; j < K; j++) 
				line_ant[i] = (line_ant[i] + rez[i][j] * line[j]) % mod; 
			
		i1 = i2;
		for (i = 1; i <= nr_erase; i++)
			bad[bad_erase[i]] = 0;
		
	}

	printf("%d\n", line_ant[K - 1]);

	return 0;
}