Cod sursa(job #2562587)

Utilizator KappaClausUrsu Ianis Vlad KappaClaus Data 29 februarie 2020 15:52:37
Problema Pod Scor 5
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.88 kb
#include <bits/stdc++.h>

using namespace std;

struct Matrix
{
    vector<vector<int>> value;
    int rows, cols;

    Matrix(int rows, int cols, string type = "default")
    {
        this->rows = rows;
        this->cols = cols;

        this->value.resize(this->rows + 1, vector<int>(this->cols + 1, 0));

        if(type == "identity")
            for(int i = 1; i <= this->rows; ++i)
                this->value[i][i] = 1;

        if(type == "problem-type")
        {
            for(int i = 1; i < this->rows; ++i)
                this->value[i + 1][i] = 1,
                this->value[i][this->cols] = 1;

            value[this->rows][this->cols] = 1;
        }

    }


    Matrix operator * (const Matrix& A)
    {
        Matrix REZ(this->rows, A.cols);

        for(int i = 1; i <= this->rows; ++i)
            for(int j = 1; j <= A.cols; ++j)
                for(int k = 1; k <= this->cols; ++k)
                    REZ.value[i][j] = (REZ.value[i][j] + 1LL*this->value[i][k]*A.value[k][j] % 9901) % 9901;

        return REZ;
    }

    Matrix operator ^ (const int N)
    {
        if(N == 0) return Matrix(this->rows, this->cols, "identity");

        if(N == 1) return *this;

        Matrix X = *this ^ (N / 2);
        X = X * X;
        if(N & 1) X = X * *this;

        return X;
    }
};


int main()
{
    ifstream fin("pod.in");
    ofstream fout("pod.out");

    int N, M, K;
    fin >> N >> M >> K;

    vector<int> OBSTACLES_POSITIONS;

    Matrix DP(1, K);

    for(int i = 1; i <= M; ++i)
    {
        int obstacle_position;
        fin >> obstacle_position;

        if(obstacle_position == N)
        {
            fout << 0 << '\n';
            return 0;
        }

        if(obstacle_position <= K)
            DP.value[1][obstacle_position] = -1;
        else
            OBSTACLES_POSITIONS.push_back(obstacle_position);
    }

    DP.value[1][0] = 1;

    for(int i = 1; i <= K; ++i)
        if(DP.value[1][i] != -1)
            for(int j = i - 1; j >= 0; --j)
                if(DP.value[1][j] != -1)
                    DP.value[1][i] = (DP.value[1][i] + DP.value[1][j]) % 9901;

    for(int i = 1; i <= K; ++i)
        if(DP.value[1][i] == -1)
            DP.value[1][i] = 0;


    if(N <= K)
    {
        fout << DP.value[1][N] << '\n';
        return 0;
    }

    Matrix X(K, K, "problem-type");


    sort(OBSTACLES_POSITIONS.begin(), OBSTACLES_POSITIONS.end());
    OBSTACLES_POSITIONS.push_back(N);

    int last_obstacle_position = K;

    for(int current_obstacle_position : OBSTACLES_POSITIONS)
    {
        DP = DP * (Matrix(K, K, "problem-type") ^ (current_obstacle_position - last_obstacle_position));

        if(current_obstacle_position != N) DP.value[1][K] = 0;

        last_obstacle_position = current_obstacle_position;
    }

    fout << DP.value[1][K] << '\n';
}