Cod sursa(job #341577)

Utilizator savimSerban Andrei Stan savim Data 18 august 2009 21:19:40
Problema Robotei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.94 kb
#include <stdio.h>
#include <string.h>

#define MAX_N 1024
#define MAX_M 667000

int n, m, X, Y, modX, modY, offsetX, offsetY;
int len, stop = 1;
int timp[MAX_N][MAX_N], use[MAX_N][MAX_N];
int nr[MAX_N][MAX_N], lin[MAX_N], col[MAX_N];
int sol[MAX_M];

void cit() {
	freopen("robotei.in", "r", stdin);
	freopen("robotei.out", "w", stdout);

	scanf("%d %d %d %d %d %d %d %d", &n, &m, &X, &Y, &modX, &modY, &offsetX, &offsetY);
}

inline int nextX(int k) {
	return (k * k + offsetX) % modX;
}                 

inline int nextY(int k) {
	return (k * k + offsetY) % modY;
}

void get_len() {
	//determin lungimea ciclului din care face parte X, Y
	int p = X, q = Y, nr = 0;
	while (nr < modX * modY + 10) {
		nr++;
    	p = nextX(p);
		q = nextY(q);

		if (p == X && q == Y) {
        	len = nr;
			break;
		}
	}
}

void bfs(int p, int q) {
	if (use[p][q]) return;
	use[p][q] = 1;

	int i = nextX(p), j = nextY(q);
	bfs(i, j);

	if (p == i && q == j) return;
	if (i == X && j == Y) timp[p][q] = 1;
	else if (timp[i][j]) timp[p][q] = timp[i][j] + 1;
}

void get_time() {
	//calculez in cat timp ajung de la o pozitie p, q la X, Y
	use[X][Y] = 1;
	for (int i = 0; i < modX; i++)
		for (int j = 0; j < modY; j++) {
			if (!use[i][j])				
           		bfs(i, j);
           	nr[i][j] = 1;
        }
}

void work(int m) {
	//avand matricea nr[i][j] = cati robotei sunt in celula i, j la momentul 1, 
    //calculez de cate ori trece un robotel prin (X, Y)
	for (int i = 0; i < modX; i++)  
        for (int j = 0; j < modY; j++)
            if (timp[i][j] || (i == X && j == Y)) {  
                if (len == 0) {  
                    //X,Y nu e pe vreun ciclu  
                    if (timp[i][j] <= m) sol[1] += nr[i][j];  
                }  
                else if (m >= timp[i][j]) {  
                    int add = (m - timp[i][j]) / len + 1;  
                    sol[add] += nr[i][j];
					if (add > stop) stop = add;
                }  
            }  
            else if (!timp[i][j] && !(i == X && j == Y)) sol[0] += nr[i][j];  
}

void up_nr(int k, int A, int B, int P, int Q) {
    for (int i = A; i < B; i++)  
        lin[nextX(i)]++;  
    for (int i = P; i < Q; i++)  
        col[nextY(i)]++; 
    
    for (int i = 0; i < modX; i++)  
        for (int j = 0; j < modY; j++)  
            nr[i][j] += k * lin[i] * col[j];  
  
    memset(lin, 0, sizeof(lin));
    memset(col, 0, sizeof(col));
}

void add_nn() {
	memset(nr, 0, sizeof(nr));
  
  	up_nr(1, modX, n, 0, n);
  	up_nr(1, 0, n, modY, n);
    up_nr(-1, modX, n, modY, n);
}

void solve() {
	get_len();	
	get_time();

	work(m);
	add_nn();
	work(m - 1);

}

void write() {
	for (int i = 0; i <= stop; i++)
		if (sol[i]) 
			printf("%d %d\n", i, sol[i]);
}

int main() {

	cit();
	if (X < modX && Y < modY)
    	solve();
    else {
        sol[0] = n * n - 1;
        sol[1] = 1;
    }
	write();

	return 0;
}