Cod sursa(job #467253)

Utilizator ProtomanAndrei Purice Protoman Data 28 iunie 2010 13:33:59
Problema Pod Scor 50
Compilator cpp Status done
Runda Stelele Informaticii 2010, clasele X-XII, Ziua 2 Marime 2.38 kb
#include <algorithm>
#include <stdio.h>
#include <string.h>

#define MAX 1024
#define restRez 9901

using namespace std;

int matRec[21][21], matRest[21][21], matTemp[21][21];
int n, m, k, pa;
int v[MAX];
int sol[21], solN[21];

inline void inmulteste(int matProd[21][21], int matFact[21][21])
{
    for (int i = 0; i < k; i++)
        for (int j = 0; j < k; j++)
        {
            matTemp[i][j] = 0;
            for (int h = 0; h < k; h++)
                matTemp[i][j] = (matTemp[i][j] + matProd[i][h] * matFact[h][j]) % restRez;
        }

    for (int i = 0; i < k; i++)
        for (int j = 0; j < k; j++)
            matProd[i][j] = matTemp[i][j];
}

inline void putLog(int x)
{
    for (int i = 0; i < k; i++)
        for (int j = 0; j < k; j++)
            matRest[i][j] = (i == j)? 1 : 0;

    for (; x > 1; x /= 2)
    {
        if (x & 1)
            inmulteste(matRest, matRec);

        inmulteste(matRec, matRec);
    }

    inmulteste(matRec, matRest);
}

int main()
{
    freopen("pod.in", "r", stdin);
    freopen("pod.out", "w", stdout);

    scanf("%d %d %d", &n, &m, &k);

    for (int i = 1; i <= m; i++)
        scanf("%d", &v[i]);
    v[++m] = n + 1;

    sort(v + 1, v + 1 + m);

    for (int i = 0; i < k; i++)
        sol[i] = 0;
    sol[k - 1] = 1;
    pa = 0;

    for (int s = 1; s <= m; s++)
    {
        memset(matRec, 0, sizeof(matRec));

        for (int i = 0; i < k - 1; i++)
            matRec[i + 1][i] = 1;

        matRec[0][k - 1] = matRec[k - 1][k - 1] = 1;

        putLog(v[s] - 1 - pa);

        if (v[s] - 1 - pa)
        {
            memset(solN, 0, sizeof(solN));

            for (int i = 0; i < k; i++)
                for (int j = 0; j < k; j++)
                    solN[i] = (solN[i] + sol[j] * matRec[j][i]) % restRez;

            for (int i = 0; i < k; i++)
                sol[i] = solN[i];
        }

        pa = v[s] - 1;

        if (s == m)
            break;

        for (; pa < min(v[s] + k, v[s + 1] - 1); pa++)
        {
            int lk = sol[0];
            for (int i = 0; i < k - 1; i++)
                sol[i] = sol[i + 1];
            if (pa + 1 != v[s])
                sol[k - 1] = (sol[k - 1] + lk) % restRez;
            else sol[k - 1] = 0;
        }
    }

    printf("%d\n", sol[k - 1]);

    fclose(stdin);
    fclose(stdout);
    return 0;
}