Cod sursa(job #2504943)

Utilizator MarianConstantinMarian Constantin MarianConstantin Data 5 decembrie 2019 19:50:42
Problema Pod Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.97 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <bitset>
#include <algorithm>
#define pb push_back

using namespace std;

ifstream fin("pod.in");
ofstream fout("pod.out");
const int MAXK = 25, MOD = 9901;

vector<int> imp;
bitset<MAXK> vis;
int inpN, inpM, k;

struct Matrix{
    int mat[MAXK][MAXK], n, m;
    Matrix() {
        n = 0;
        m = 0;
        for (int i = 0; i < MAXK; ++i)
            for (int j = 0; j < MAXK; ++j)
                mat[i][j] = 0;
    }
    Matrix(int _n, int _m) {
        n = _n;
        m = _m;
        for (int i = 0; i < MAXK; ++i)
            for (int j = 0; j < MAXK; ++j)
                mat[i][j] = 0;
    }
    Matrix &operator=(const Matrix &other) {
        n = other.n;
        m = other.m;
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < m; ++j)
                mat[i][j] = other.mat[i][j];
        return *this;
    }
    Matrix multiply(const Matrix &other) {
        Matrix result;
        result.n = n;
        result.m = other.m;
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < other.m; ++j)
                for (int k = 0; k < m; ++k)
                    result.mat[i][j] +=  mat[i][k] * other.mat[k][j];
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < other.m; ++j)
                result.mat[i][j] %= MOD;
        return result;
    }
    void setUnitMatrix() {
        if (n == m)
            for (int i = 0; i < n; ++i)
                mat[i][i] = 1;
    }
    Matrix pow(int exp) {
        Matrix res(n, n), mult;
        res.setUnitMatrix();
        mult = *this;
        while (exp) {
            if (exp & 1)
                res = res.multiply(mult);
            mult = mult.multiply(mult);
            exp >>= 1;
        }
        return res;
    }
    ~Matrix() {

    }
}dp, val;

bool read() {
    fin >> inpN >> inpM >> k;
    for (int i = 0; i < inpM; ++i) {
        int x;
        fin >> x;
        if (x == inpN)
            return true;
        if (x <= k)
            vis[x] = 1;
        else
            imp.pb(x);
    }
    return false;
}

void initialize() {
    dp.n = k;
    dp.m = k;
    val.n = 1;
    val.m = k;
    for (int i = 0; i < k - 1; ++i)
        dp.mat[i + 1][i] = 1;
    dp.mat[0][k - 1] = dp.mat[k - 1][k - 1] = 1;
    if (!vis[1])
        val.mat[0][0] = 1;
    for (int i = 1; i < k; ++i)
        if (!vis[i + 1])
            val.mat[0][i] += val.mat[0][i - 1];
    if (!vis[k])
        ++val.mat[0][k - 1];
    imp.pb(inpN);
}

void solve() {
    int last = k;
    for (const auto &it: imp) {
        int diff = it - last;
        last = it;
        val = val.multiply(dp.pow(diff));
        if (it != inpN)
            val.mat[0][k - 1] = 0;
    }
}

int main() {
    if (read()) {
        fout << 0;
        return 0;
    }
    sort(imp.begin(), imp.end());
    initialize();
    solve();
    fout << val.mat[0][k - 1];
    return 0;
}