Cod sursa(job #1088952)

Utilizator romircea2010FMI Trifan Mircea Mihai romircea2010 Data 21 ianuarie 2014 00:12:08
Problema Rsir Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.36 kb
#include <fstream>
#include <iostream>
#define MMax 7010

using namespace std;

struct stare
{
    int val, pred;
    stare() {}
    stare (const int _val, const int _pred)
    {
        val = _val;
        pred = _pred;
    }
    bool operator ==(const stare &other) const
    {
        return (val == other.val) && (pred == other.pred);
    }
    bool operator !=(const stare &other) const
    {
        return (val != other.val) || (pred != other.pred);
    }
};

///T[n] = a * T[n-2]^2 + b * T[n-1]^2 + x * T[n-2] + y * T[n-1] + z

int T0, T1, a, b, x, y, z, m;
int PrecA[MMax], PrecB[MMax];
long long n;
//0 <= a, b, x, y, z <= 1.000
//0 <= T0, T1 <= 1.000.000.000
//0 <= n <= 10^16
//1 <= M <= 7.000

void Read()
{
    ///T0, T1, a, b, x, y, z, M si n
    ifstream f ("rsir.in");
    f>>T0>>T1>>a>>b>>x>>y>>z>>m;
    f>>n;
    f.close();
}

inline stare next_stare(const stare &X)
{
    int aux = PrecA[X.pred] + PrecB[X.val] + z;
    while (aux >= m)
        aux -= m;
    return stare(aux, X.val);
}

void Precalc()
{
    T1 %= m;
    T0 %= m;
    for (int i = 0 ; i < m; ++i)
        PrecA[i] = (1LL * i * i * a + 1LL * x * i) % m,
        PrecB[i] = (1LL * i * i * b + 1LL * y * i) % m;
}

void Write(int nrpasi)
{
    ofstream g("rsir.out");
    if (nrpasi == 0)
    {
        g<<T0<<"\n";
    }
    else if (nrpasi == 1)
        g<<T1<<"\n";
    else
    {
        stare st = stare(T1, T0);
        for (--nrpasi; nrpasi > 0; --nrpasi)
            st = next_stare(st);
        g<<st.val<<"\n";
    }
    g.close();
}

void Solve()
{
    Precalc();
    stare A, B, aux;
    A = B = stare(T1, T0);
    int count = 0, lgcoada, lgciclu;
    while (!count || A != B)
    {
        ++count;
        A = next_stare(A), B = next_stare(next_stare(B));
    }
    lgcoada = lgciclu = 0;
    stare ciclu = A, cpyciclu = A;
    while (!lgciclu || ciclu != cpyciclu)
    {
        ++lgciclu;
        cpyciclu = next_stare(cpyciclu);
    }
    stare inc = stare(T1, T0), coada = A;
    while (!lgcoada || inc != coada)
    {
        ++lgcoada;
        inc = next_stare(inc), coada = next_stare(coada);
    }
    int nrpasi;
    if (n <= lgcoada)
        nrpasi = n;
    else
        nrpasi = lgcoada + (n - lgcoada) % lgciclu;
    Write(nrpasi);
}

int main()
{
    Read();
    Solve();
    return 0;
}