Cod sursa(job #1046160)

Utilizator scipianusFMI Ciprian Olariu scipianus Data 2 decembrie 2013 18:37:15
Problema Robotei Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.95 kb
#include <fstream>
#include <algorithm>
#include <vector>
#include <queue>
#define pii pair<int, int>
#define x first
#define y second
using namespace std;
int n, m, X, Y, modX, modY, offsetX, offsetY;
int sol[667000];
int Next[1010000], dist[1010000], cycle_len;
vector <int> GT[1010000];
queue <int> Q;
bool Skip;

inline void Read()
{
	ifstream fin("robotei.in");
	fin >> n >> m >> X >> Y >> modX >> modY >> offsetX >> offsetY;
	fin.close();
	if(X >= modX || Y >= modY)
	{
		if(X < n && Y <n)
		{
			sol[0] = n * n - 1;
			sol[1] = 1;
		}
		else
			sol[0] = n * n;
		Skip = true;
	}
}

inline int Code(pii poz)
{
	// codifica o pozitie
	return poz.x * 1000 + poz.y;
}

inline pii Decode(int code)
{
	// decodifica o pozitie
	return make_pair(code / 1000, code % 1000);
}

inline void BuildGraph()
{
	int i, j, c;
	for(i = 0; i < modX; ++i)
	{
		for(j = 0; j < modY; ++j)
		{
			c = Code(make_pair(i, j));
			// graful normal - fiecare nod are gradul de iesire 1
			Next[c] = Code(make_pair((i * i + offsetX) % modX, (j * j + offsetY) % modY));
			// graful transpus
			GT[Next[c]].push_back(c);
		}
	}
}

inline void GetDistances()
{
	// gaseste distantele de la fiecare pozitie la (X, Y)
	int i, j, c, now;
	vector <int>::iterator it;
	for(i = 0; i < modX; ++i)
	{
		for(j = 0; j < modY; ++j)
		{
			c = Code(make_pair(i, j));
			dist[c] = 1000000000;
		}
	}
	now = Code(make_pair(X, Y));
	dist[now] = 0;
	Q.push(now);
	while(!Q.empty())
	{
		now = Q.front();
		Q.pop();
		for(it = GT[now].begin(); it != GT[now].end(); ++it)
		{
			if(dist[*it] > dist[now] + 1)
			{
				dist[*it] = dist[now] + 1;
				Q.push(*it);
			}
		}
	}
}

inline void GetCycleLength()
{
	// gaseste lungimea ciclului din care face parte (X, Y)
	int c = Code(make_pair(X, Y));
	cycle_len = dist[Next[c]] + 1;
}

inline void SolveIntern()
{
	// iau in calcul doar punctele din dreptunghiul modX x modY
	int i, j, c, nr;
	for(i = 0; i < modX; ++i)
	{
		for(j = 0; j < modY; ++j)
		{
			c = Code(make_pair(i, j));
			if(dist[c] <= m)
			{
				nr = (m - dist[c]) / cycle_len + 1;
				sol[nr]++;
			}
			else
				sol[0]++;
		}
	}
}

inline void SolveExtern()
{
	// iau in calcul doar punctele din afara dreptunghiului modX x modY
	int i, j, c, nr, robotei;
	for(i = 0; i < modX; ++i)
	{
		for(j = 0; j < modY; ++j)
		{
			robotei = ((n - 1 - i) / modX + 1) * ((n - 1 - j) / modY + 1) - 1;
			c = Code(make_pair(i, j));
			c = Next[c];
			if(dist[c] + 1 <= m)
			{
				nr = (m - dist[c] - 1) / cycle_len + 1;
				sol[nr] += robotei;
			}
			else
				sol[0] += robotei;
		}
	}
}

inline void Write()
{
	int i;
	ofstream fout("robotei.out");
	for(i = 0; i <= m; ++i)
		if(sol[i])
			fout << i << ' ' << sol[i] << "\n";
	fout.close();
}

int main()
{
	Read();
	if(!Skip)
	{
		BuildGraph();
		GetDistances();
		GetCycleLength();
		SolveIntern();
		SolveExtern();
	}
	Write();
	return 0;
}