Cod sursa(job #851908)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 10 ianuarie 2013 16:49:42
Problema Robotei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.87 kb
#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>

using namespace std;

const int MaxN = 1000005;
const int MaxC = 1005;

int N, M, ModX, ModY, OffsetX, OffsetY;

struct Node {
    int x, y, v;

    Node() {}

    Node(const int x, const int y) {
        this->x = x, this->y = y;
        v = ModY * x + y;
    }

    Node(const int v) {
        this->x = v / ModY, this->y = v % ModY;
    }
};

Node Special;
int G[MaxN], CycleLength, Distance[MaxN], WX[MaxC], WY[MaxC], Solution[MaxN];
bool Visited[MaxN];

inline int NextX(const int X) {
    return (X * X + OffsetX) % ModX;
}

inline int NextY(const int Y) {
    return (Y * Y + OffsetY) % ModY;
}

void BuildGraph() {
    for (int X = 0; X < ModX; ++X)
        for (int Y = 0; Y < ModY; ++Y)
            G[Node(X, Y).v] = Node(NextX(X), NextY(Y)).v;
}

void FindCycle() {
    int V = Special.v;
    do {
        Visited[V] = true, ++CycleLength;
        V = G[V];
    } while (!Visited[V]);
    if (V != Special.v)
        CycleLength = MaxN;
}

int GetDistance(const int X) {
    if (Visited[X])
        return Distance[X];
    Visited[X] = true;
    Distance[X] = GetDistance(G[X]);
    Distance[X] += (Distance[X] != -1);
    return Distance[X];
}

inline void BuildDistances(const int Source) {
    memset(Visited, 0, sizeof(Visited));
    memset(Distance, -1, sizeof(Distance));
    Visited[Source] = true, Distance[Source] = 0;
    for (int X = 0; X < ModX; ++X)
        for (int Y = 0; Y < ModY; ++Y)
            if (!Visited[Node(X, Y).v])
                GetDistance(Node(X, Y).v);
}

void Solve() {
    if (Special.x >= ModX || Special.y >= ModY) {
        Solution[0] = N * N - 1, Solution[1] = 1;
        return;
    }
    BuildGraph();
    FindCycle();
    BuildDistances(Special.v);
    Special = Node(NextX(Special.x), NextY(Special.y));
    --M;
    for (int V = 0; V < N; ++V)
        ++WX[NextX(V)], ++WY[NextY(V)];
    for (int X = 0; X < ModX; ++X) {
        for (int Y = 0; Y < ModY; ++Y) {
            int Weight = WX[X] * WY[Y] - (Special.x == X && Special.y == Y);
            int V = Node(X, Y).v, Frequence = 0;
            if (Distance[V] != -1 && M >= Distance[V])
                Frequence += (1 + (M - Distance[V]) / CycleLength);
            Solution[Frequence] += Weight;
        }
    }
    ++Solution[1 + (M + 1) / CycleLength];
}

void Read() {
    assert(freopen("robotei.in", "r", stdin));
    int X, Y; assert(scanf("%d %d %d %d", &N, &M, &X, &Y) == 4);
    assert(scanf("%d %d %d %d", &ModX, &ModY, &OffsetX, &OffsetY) == 4);
    Special = Node(X, Y);
}

void Print() {
    assert(freopen("robotei.out", "w", stdout));
    for (int i = 0; i <= M + 1; ++i)
        if (Solution[i] > 0)
            printf("%d %d\n", i, Solution[i]);
}

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