Cod sursa(job #275021)

Utilizator CezarMocanCezar Mocan CezarMocan Data 10 martie 2009 10:14:33
Problema Robotei Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.46 kb
#include <cstdio>
#include <vector>
#define MAXN 44500 
#define MAXM 666800
#define MAXP 1010

using namespace std;

struct pozitie {
	int x, y;
};

int n, m, x, y, offX, offY, modX, modY, X, Y, lg;
int i, j, nx, ny, nrp;
int px[MAXN], py[MAXN];
int antx[MAXP][MAXP], anty[MAXP][MAXP];
int sol[MAXM];
bool viz[MAXP][MAXP];
vector <int> vx[MAXP][MAXP], vy[MAXP][MAXP];
int ct[MAXP][MAXP];

int urm(int t, int off, int mod) {
	return (t * t + off) % mod;
}

void baga(int x, int y) {	
	while (viz[x][y] == 0) {
		viz[x][y] = 1;
		nx = urm(x, offX, modX);
		ny = urm(y, offY, modY);
//		aux.x = x; aux.y = y;
		vx[nx][ny].push_back(x);
		vy[nx][ny].push_back(y);
		x = nx; y = ny;
	}
}

void bf(int x, int y) {
	int p, u, xnou, ynou;
	pozitie c[MAXP * MAXP];

	memset(ct, -1, sizeof(ct));

	p = u = 1;
	c[1].x = x; c[1].y = y;
	viz[x][y] = 1;
	ct[x][y] = 0;

	while (p <= u) {
		nx = c[p].x;
		ny = c[p].y;
		for (i = 0; i < vx[nx][ny].size(); i++) {
			xnou = vx[nx][ny][i];
			ynou = vy[nx][ny][i];
			if (viz[xnou][ynou] == 0) {
				ct[xnou][ynou] = ct[nx][ny] + 1;
				u++;
				c[u].x = xnou; c[u].y = ynou;
				viz[xnou][ynou] = 1;
			}
		}
		p++;
	}
}

int main() {
	freopen("robotei.in", "r", stdin);
	freopen("robotei.out", "w", stdout);

	//deci... am de facut mai multe chestii:
	//1 -> sa gasesc perioada pe care se afla X Y -> daca nu e pe perioada am caz particular
	//2 -> sa vad toate coordonatele [pe rand, pentru X si Y, sunt independente] in ce merg [de alea <= modX si modY]
	//3 -> fac un graf cu fiecare patratel in cine merge (merge intr-o singura chestie) si apoi fac BF pe graful invers, pornind din X,Y
	//4 -> vad in cati pasi ajung la fiecare nod, fac M - nr de pasi si vad de cate ori mai pot ajunge la X,Y folosind ce am aflat la pasu 1
	
	scanf("%d%d%d%d%d%d%d%d", &n, &m, &X, &Y, &modX, &modY, &offX, &offY);
	x = X; y = Y;

	for (i = 2; i <= modX * modY; i++) {
		nx = urm(x, offX, modX);
		ny = urm(y, offY, modY);
//		printf("%d %d\n", nx, ny);
		x = nx; y = ny;
		if (x == X && y == Y)
			break;
	}

	if (x == X && y == Y) 
		lg = i - 1;

//	fprintf(stderr, "%d\n", lg);
	
	for (i = 0; i < n; i++) {
		px[(1LL * i * i + offX) % modX]++;
		py[(1LL * i * i + offY) % modY]++;
	}

/*	for (i = 0; i < n; i++) {
		printf("%d %d\n", px[i], py[i]);
	}*/

/*	for (i = 0; i < modX; i++) {
		for (j = 0; j < modY; j++)
			printf("%d ", px[i] * py[j]);
		printf("\n");
	}*/

	
	//tre sa fac BF-ul ala invers
	
	for (i = 0; i < modX; i++)
		for (j = 0; j < modY; j++) 
			if (viz[i][j] == 0) 
				baga(i, j);

//	fprintf(stderr, "**********\n");

	memset(viz, 0, sizeof(viz));
	bf(X, Y);

//	fprintf(stderr, "***///***\n");

	//din BF o sa stiu fiecare pozitie cat mai are pana la X,Y si apoi o sa vad cati pasi mi-au mai ramas si stiu care e perioada la X,Y
	//aici e gata BF-ul si urmeaza pentru fiecare pozitie sa vad de cate ori ajung in (X, Y)
	m--;
//	printf("%d\n", ct[X][Y]);

	if (lg == 0) {
		for (i = 0; i < modX; i++)
			for (j = 0; j < modY; j++)
				if (ct[i][j] >= 0)
					sol[1] += px[i] * py[j];
				else
					sol[0] += px[i] * py[j];
		sol[0]--; sol[1]++;
	}
	else
	for (i = 0; i < modX; i++)
		for (j = 0; j < modY; j++) 
			if (lg)
				if (i == X && j == Y) {
					nrp = m - ct[i][j];
					sol[nrp / lg + 1] += px[i] * py[j] - 1;
					sol[nrp / lg + 2]++;
				}
				else
					if (ct[i][j] == -1)
						sol[0] += px[i] * py[j];
					else {
						nrp = m - ct[i][j];
						sol[nrp / lg + 1] += px[i] * py[j];
					}
			

	for (i = 0; i <= m; i++)
		if (sol[i])
			printf("%d %d\n", i, sol[i]);

	return 0;
}