Artifact Content
Not logged in

Artifact 3bd5d04ce69009dd2efded61acb77854ab3ca58d


#include <iostream>
#include <sstream>
#include <iomanip>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <algorithm>
#include <numeric>
#include <iterator>
#include <functional>
#include <complex>
#include <queue>
#include <stack>
#include <cmath>
#include <cassert>
#include <tuple>
using namespace std;
typedef long long LL;
typedef complex<double> CMP;

int gcd(int a, int b)
{
	while (a)
		swap(a, b %= a);
	return b;
}

bool is_coprime(int a, int b)
{
	return gcd(a, b) == 1;
}

class CoprimeMatrix { public:
	vector<bool> is_p;
	vector<int> primes;

	string isPossible(vector <string> coprime)
	{
		// eratos
		if (is_p.empty()) {
			is_p.assign(60, true);
			is_p[0] = is_p[1] = false;
			for (int p = 2; p < is_p.size(); ++p) if (is_p[p]) {
				primes.push_back(p);
				for (int q = p + p; q < is_p.size(); q += p)
					is_p[q] = false;
			}
		}

		return solve(coprime) ? "Possible" : "Impossible";
	}

	bool solve(const vector<string>& coprime)
	{
		const int N = coprime.size();

		// sanity
		for (int i = 0; i < N; ++i)
		for (int k = 0; k < N; ++k)
			if (coprime[i][k] != coprime[k][i])
				return false;

		// trivial case
		for (int i = 0; i < N; ++i)
		for (int k = 0; k < N; ++k)
			if (is_coprime(1 + i, 1 + k) != (coprime[i][k] == 'Y'))
				goto nontrivial;
		return true;

	nontrivial:
		for (int i = 0; i < N; ++i)
			if(coprime[i][i]=='Y')
				return false;

		vector<vector<bool>> cos;
		for (int off = 0; off < N; ++off) {
			vector<bool> co;
			for (int t = 0; t + off < N; ++t)
				co.push_back(coprime[off][off + t] == 'Y');

			// x+off coprime with k in 0,1,2,,,,co.size()-1 iff co[k]

			if (!can(co))
				return false;
			cos.push_back(co);
		}

		for (int p = 2; p < N; ++p) if (is_p[p]) {
			int last = -1;
			for(int o=0; o<cos.size() && cos[o].size()>p; ++o)
				if (cos[o][p] == false) {
					if (last!=-1 && (o-last)!=p)
						return false;
					last = o;
				}
				else {
					if (o - last >= p)
						return false;
				}
		}

		return true;
	}

	bool can(const vector<bool>& co)
	{
		// Can there be a positive n such that coprime(n,i) == co[i] ?
		vector<int> prime_factors;
		for (int p = 2; p < co.size(); ++p)
			if (is_p[p] && !co[p])
				prime_factors.push_back(p);

		for (int k = 0; k < co.size(); ++k)
			if (is_coprimev(k, prime_factors) != co[k]) {
				prime_factors.push_back(primes.back());
				for (int k = 0; k < co.size(); ++k)
					if (is_coprimev(k, prime_factors) != co[k])
						return false;
				return true;
			}
		return true;
	}

	bool is_coprimev(int k, const vector<int>& pfs)
	{
		for (int p : pfs)
			if (k%p == 0)
				return false;
		return true;
	}
};

// BEGIN CUT HERE
#include <ctime>
double start_time; string timer()
 { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); }
template<typename T> ostream& operator<<(ostream& os, const vector<T>& v)
 { os << "{ ";
   for(typename vector<T>::const_iterator it=v.begin(); it!=v.end(); ++it)
   os << '\"' << *it << '\"' << (it+1==v.end() ? "" : ", "); os << " }"; return os; }
void verify_case(const string& Expected, const string& Received) {
 bool ok = (Expected == Received);
 if(ok) cerr << "PASSED" << timer() << endl;  else { cerr << "FAILED" << timer() << endl;
 cerr << "\to: \"" << Expected << '\"' << endl << "\tx: \"" << Received << '\"' << endl; } }
#define CASE(N) {cerr << "Test Case #" << N << "..." << flush; start_time=clock();
#define END	 verify_case(_, CoprimeMatrix().isPossible(coprime));}
int main(){

CASE(0)
	string coprime_[] = {"NYNYN",
 "YNYYN",
 "NYNYN",
 "YYYNY",
 "NNNYN"};
	  vector <string> coprime(coprime_, coprime_+sizeof(coprime_)/sizeof(*coprime_)); 
	string _ = "Possible"; 
END
CASE(1)
	string coprime_[] = {"NY",
 "NN"};
	  vector <string> coprime(coprime_, coprime_+sizeof(coprime_)/sizeof(*coprime_)); 
	string _ = "Impossible"; 
END
CASE(2)
	string coprime_[] = {"NYYYYN",
 "YNYNNN",
 "YYNYYY",
 "YNYNYN",
 "YNYYNY",
 "NNYNYN"};
	  vector <string> coprime(coprime_, coprime_+sizeof(coprime_)/sizeof(*coprime_)); 
	string _ = "Possible"; 
END
CASE(3)
	string coprime_[] = {"NN",
 "NN"};
	  vector <string> coprime(coprime_, coprime_+sizeof(coprime_)/sizeof(*coprime_)); 
	string _ = "Impossible"; 
END
CASE(4)
// both x and x+1 and x+2 are coprime with 2
	string coprime_[] = 
{
	"NYYY",
	"YNYY",
	"YYNY",
	"YYYN",
};
	  vector <string> coprime(coprime_, coprime_+sizeof(coprime_)/sizeof(*coprime_)); 
	string _ = "Impossible"; 
END
CASE(5)
// x+1 == 1
string coprime_[] = { "NY", "YY" };
	  vector <string> coprime(coprime_, coprime_+sizeof(coprime_)/sizeof(*coprime_)); 
	string _ = "Impossible"; 
END
CASE(6)
string coprime_[] = { "Y" };
vector <string> coprime(coprime_, coprime_ + sizeof(coprime_) / sizeof(*coprime_));
string _ = "Possible";
END
}
// END CUT HERE