Problem:
Problem F:
Directional Resemblance
Vectors have their directions and two vectors make an angle between them. Given a set of three-dimensional vectors, your task is to find the pair among them that makes the smallest angle.
Input
The input is a sequence of datasets. A dataset specifies a set of three-dimensional vectors, some of which are directly given in the dataset and the others are generated by the procedure described below.
Each dataset is formatted as follows.
m
n
S
W
x
1
y
1
z
1
x
2
y
2
z
2
:
x
m
y
m
z
m
The first line contains four integers
m
,
n
,
S
, and
W
.
The integer
m
is the number of vectors whose three components are directly specified in the
dataset. Starting from the second line,
m
lines have the three components of
m
vectors. The
i
-th line of which indicates the vector
v
i
= (
x
i
,
y
i
,
z
i
). All the vector components are positive integers less than or equal to 100.
The integer
n
is the number of vectors generated by the following procedure.
int g = S;
for(int i=m+1; i<=m+n; i++) {
  x[i] = (g/7)    %100 + 1;
  y[i] = (g/700)  %100 + 1;
  z[i] = (g/70000)%100 + 1;
  if( g%2 == 0 ) { g = (g/2); }
  else           { g = (g/2) ^ W; }
}
For
i = m + 1, . . . , m + n
, the
i
-th vector
v
i
of the set has three components
x[i]
,
y[i]
, and
z[i]
generated by this procedure.
Here, values of
S
and
W
are the parameters
S
and
W
given in the first line of the dataset. You may assume 1 ≤
S
≤ 10
9
and 1 ≤
W
≤ 10
9
.
The total number of vectors satisfies 2 ≤
m + n
≤ 12 × 10
4
. Note that exactly the same vector may be specified twice or more in a single dataset.
A line containing four zeros indicates the end of the input. The total of
m+n
for all the datasets in the input never exceeds 16 × 10
5
.
Output
For each dataset, output the pair of vectors among the specified set with the smallest non-zero angle in between. It is assured that there are at least two vectors having different directions.
Vectors should be indicated by their three components. The output for a pair of vectors
v
a
and
v
b
should be formatted in a line as follows.
x
a
y
a
z
a
x
b
y
b
z
b
Two vectors (
x
a
,
y
a
,
z
a
) and (
x
b
,
y
b
,
z
b
) are ordered in the dictionary order, that is,
v
a
<
v
b
if
x
a
<
x
b
, or if
x
a
= x
b
and
y
a
<
y
b
, or if
x
a
= x
b
,
y
a
= y
b
and
z
a
<
z
b
. When a vector pair is output, the smaller vector in this order should be output first.
If more than one pair makes the equal smallest angle, the pair that is the smallest among them in the dictionary order between vector pairs should be output. The pair (
v
i
,
v
j
) is smaller than the pair (
v
k
,
v
l
) if
v
i
<
v
k
, or if
v
i
= v
k
and
v
j
<
v
l
.
Sample Input
4 0 2013 1124
1 1 1
2 2 2
2 1 1
1 2 1
2 100 131832453 129800231
42 40 46
42 40 46
0 100000 7004674 484521438
0 0 0 0
Output for the Sample Input
1 1 1 1 2 1
42 40 46 83 79 91
92 92 79 99 99 85

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
//using namespace std;

typedef long double LD;

const LD INF = 1e15;
const LD eps = 1e-13;
const int N = 155555;

int n, m, S, W;

inline LD norm(const LD &x) {
	return x * x;
}

struct OriP {
	int x, y, z;
} p[N];

struct Point {
	LD x, y, z;
	int id;
	Point() = default;
	Point(const OriP &p) {
		x = p.x;
		y = p.y;
		z = p.z;
	}
	const LD& operator [] (int index) const {
		if (index == 0) {
			return x;
		} else {
			return index == 1 ? y : z;
		}
	}
	friend LD dist(const Point &a, const Point &b) {
		LD result = 0.0;
		for (int i = 0; i < 3; ++i) {
			result += norm(a[i] - b[i]);
		}
		return result;
	}
} point[N];

inline bool operator == (const OriP &p, const OriP &q) {
	return p.x == q.x && p.y == q.y && p.z == q.z;
}

inline bool operator < (const OriP &p, const OriP &q) {
	if (p.x != q.x) {
		return p.x < q.x;
	}
	if (p.y != q.y) {
		return p.y < q.y; 
	} else {
		return p.z < q.z;
	}
}

inline bool operator > (const OriP &p, const OriP &q) {
	if (p.x != q.x) {
		return p.x > q.x;
	}
	if (p.y != q.y) {
		return p.y > q.y; 
	} else {
		return p.z > q.z;
	}
}

struct Rectangle {
	LD min[3], max[3];
	Rectangle() {
		min[0] = min[1] = min[2] = INF;
		max[0] = max[1] = max[2] = -INF;
	}
	void add(const Point &p) {
		for (int i = 0; i < 3; ++i) {
			min[i] = std::min(min[i], p[i]);
			max[i] = std::max(max[i], p[i]);
		}
//assert(min[0] > -1 && min[1] > -1 && min[2] > -1);
//assert(min[0] < 100 && min[1] < 100 && min[2] < 100);
	}
	double dist(const Point &p) {
	
	//std::cout << min[0] << " " << min[1] << " " << min[2] << std::endl;
	//std::cout << max[0] << " " << max[1] << " " << max[2] << std::endl;
		double result = 0;
		for (int i = 0; i < 3; ++i) {
			result += norm(std::min(std::max(p[i], min[i]), max[i]) - p[i]);
			//result += std::max(norm(max[i] - p[i]), norm(min[i] - p[i]));
		}
//assert(min[0] > -1 && min[1] > -1 && min[2] > -1);
//assert(min[0] < 100 && min[1] < 100 && min[2] < 100);
//return INF;
		return result;
	}
};

struct Node {
	Point seperator;
	Rectangle rectangle;
	int child[2];
	void reset(const Point &p) {
		seperator = p;
		rectangle = Rectangle();
		rectangle.add(p);
		child[0] = child[1] = 0;
	}
} tree[N << 1];

int size, pivot;

inline int sign(LD x) {
	if (x < -eps) {
		return -1;
	}
	else {
		return x > eps;
	}
}

inline bool compare(const Point &a, const Point &b) {
//std::cerr << "cmp" << " " << pivot << " " << a.x << " " << a.y << " " << a.z << " " << b.x << " " << b.y << " " << b.z << std::endl;
//std::cerr << a[pivot] << " " << b[pivot] << std::endl;
	if (sign(a[pivot] - b[pivot]) == 0) {
//std::cerr << "check_id " << a.id << " " << b.id << std::endl;
		if (a.id == -1 || b.id == -1) {
			return true;
		}
		return p[a.id] < p[b.id];
	} else {
		return a[pivot] < b[pivot];
	}
}

inline int build(int l, int r, int type = 1) {
//std::cout << l << " " << r << " " << std::endl;
	pivot = type;
	if (l > r) {
		return 0;
	}
	int x = ++size;
	int mid = l + r >> 1;
	std::nth_element(point + l, point + mid, point + r, compare);
	tree[x].reset(point[mid]);
//std::cout << l << " " << mid << " " << r << " " << tree[x].seperator.id << std::endl;
//std::cout << tree[x].seperator.x << " " << tree[x].seperator.y << " " << tree[x].seperator.z << " " << std::endl;
	for (int i = l; i <= r; ++i) {
		tree[x].rectangle.add(point[i]);
	}
	tree[x].child[0] = build(l, mid - 1, (type + 1) % 3);
	tree[x].child[1] = build(mid + 1, r, (type + 1) % 3);
	
//assert(tree[x].rectangle.min[0] > -1 && tree[x].rectangle.min[1] > -1 && tree[x].rectangle.min[2] > -1);
//assert(tree[x].rectangle.min[0] < 100 && tree[x].rectangle.min[1] < 100 && tree[x].rectangle.min[2] < 100);
	return x;
}

inline void query(int x, const Point &u, std::pair<LD, int> & answer, int type = 1) {
//std::cout << "root = " << x << " " << u.x << " " << u.y << " " << u.z << std::endl;
	if (!x) {
		return;
	}
	pivot = type;
//std::cout << tree[x].rectangle.dist(u) << std::endl;
	if (tree[x].rectangle.dist(u) > answer.first + 1e-6) {
		return;
	}
	double d = dist(tree[x].seperator, u);
	
/*std::cout << "asdfasf" << std::endl;
std::cout << u.x << " " << u.y << " " << u.z << std::endl;
std::cout << tree[x].seperator.x << " " << tree[x].seperator.y << " " << tree[x].seperator.z << " " << std::endl;
std::cout << d << " " << sign(d) << std::endl;
*/
	
	if (sign(d) && (sign(d - answer.first) == -1 || sign(d - answer.first) == 0 && p[tree[x].seperator.id] < p[answer.second])) {
		answer = std::make_pair(d, tree[x].seperator.id);
	}
//std::cerr << "gogogo" << std::endl;
	if (compare(u, tree[x].seperator)) {
		query(tree[x].child[0], u, answer, (type + 1) % 3);
		query(tree[x].child[1], u, answer, (type + 1) % 3);
	} else {
		query(tree[x].child[1], u, answer, (type + 1) % 3);
		query(tree[x].child[0], u, answer, (type + 1) % 3);
	}
} 


int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);
	
	while (std::cin >> m >> n >> S >> W) {
		if (!m && !n && !S && !W) {
			return 0;
		}
		for (int i = 1; i <= m; ++i) {
			std::cin >> p[i].x >> p[i].y >> p[i].z;
		}
		int g = S;
		for (int i = 1; i <= n; ++i) {
		//std::cerr << i << std::endl;
			p[i + m].x = (g / 7) % 100 + 1;
			p[i + m].y = (g / 700) % 100 + 1;
			p[i + m].z = (g / 70000) % 100 + 1;
			if (g % 2 == 0) {
				g = g / 2;	
			} else {
				g = (g / 2) ^ W;
			}
		}
		n += m;//return 0;
		
		std::pair<LD, int> nowans;
		for (int i = 1; i <= n; ++i) {
			double dist = sqrt(p[i].x * p[i].x + p[i].y * p[i].y + p[i].z * p[i].z);
			point[i].x = p[i].x / dist;
			point[i].y = p[i].y / dist;
			point[i].z = p[i].z / dist;
			point[i].id = i;
//std::cout << "node[" << i << "]= " << p[i].x << " " << p[i].y << " " << p[i].z << std::endl;
//std::cout << point[i].x << " " << point[i].y << " " << point[i].z << std::endl;
		}
		size = 0;
		build(1, n);// return 0;
		//std::cout << size << std::endl; return 0;
		//std::cout << "adsf" << std::endl;
		std::pair<int, int> ans = std::make_pair(-1, 2);
		double ansd = (p[1].x * p[2].x + p[1].y * p[2].y + p[1].z * p[2].z) 
				/ sqrt(p[1].x * p[1].x + p[1].y * p[1].y + p[1].z * p[1].z)
				/ sqrt(p[2].x * p[2].x + p[2].y * p[2].y + p[2].z * p[2].z);
		for (int i = 1; i <= n; ++i) {
			nowans = std::make_pair(INF, 0);
			Point u(p[i]);
			double d = sqrt(p[i].x * p[i].x + p[i].y * p[i].y + p[i].z * p[i].z);
			u.x /= d;
			u.y /= d;
			u.z /= d;
			u.id = -1;
//std::cerr << "query " << i << " " << std::endl;
			query(1, u, nowans);
			std::pair<int, int> now = std::make_pair(i, nowans.second);
			if (p[now.first] > p[now.second]) {
				std::swap(now.first, now.second);
			}
			int j = now.first, k = now.second;
			d = (p[j].x * p[k].x + p[j].y * p[k].y + p[j].z * p[k].z) 
				/ sqrt(p[j].x * p[j].x + p[j].y * p[j].y + p[j].z * p[j].z)
				/ sqrt(p[k].x * p[k].x + p[k].y * p[k].y + p[k].z * p[k].z);
/*std::cout << "now: " << i << " " << d << " " << nowans.second << " " << nowans.first << std::endl;
std::cout << u.x << " " << u.y << " " << u.z << std::endl;
std::cout << p[nowans.second].x << " " << p[nowans.second].y << " " << p[nowans.second].z << std::endl;	
*/			if (ans.first == -1) {
				ans = now;
				continue;
			}
			if (sign(d - ansd) == -1) {
				continue;
			}
			if (sign(d - ansd) == 1) {	
				ans = now;
				ansd = d;
			} else {
				if (p[j] < p[ans.first] || p[j] == p[ans.first] && p[k] < p[ans.second]) {
					ans = now;
				}
			}
		}
		
		//std::cerr << "123" << std::endl;
		
		std::cout << p[ans.first].x << " " << p[ans.first].y << " " << p[ans.first].z << " " 
				<< p[ans.second].x << " " << p[ans.second].y << " " << p[ans.second].z << std::endl;
	}	
}
accuracy: 1
time_ms: 3400
memory_kb: 67544
final_rank: 19

code_snippet: #pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
#include<chrono>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;

#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);

template<typename T>
void chmin(T& a, T b) {
	a = min(a, b);
}
template<typename T>
void chmax(T& a, T b) {
	a = max(a, b);
}
template<typename T>
void cinarray(vector<T>& v) {
	rep(i, v.size())cin >> v[i];
}
template<typename T>
void coutarray(vector<T>& v) {
	rep(i, v.size()) {
		if (i > 0)cout << " "; cout << v[i];
	}
	cout << "\n";
}

ll gcd(ll a, ll b) {
	a = abs(a); b = abs(b);
	if (a < b)swap(a, b);
	while (b) {
		ll r = a % b; a = b; b = r;
	}
	return a;
}





int m, n, s, w;
void solve() {
	vector<vector<int>> v(m + n);
	rep(i, m) {
		v[i].resize(3);
		rep(j, 3)cin >> v[i][j];
	}
	int g = s;
	rep(i, n) {
		v[i + m].resize(3);
		v[i + m][0] = (g / 7) % 100 + 1;
		v[i + m][1] = (g / 700) % 100 + 1;
		v[i + m][2] = (g / 70000) % 100 + 1;
		if (g % 2 == 0)g /= 2;
		else g = (g / 2) ^ w;
	}
	//erase same vector
	{
		vector<vector<int>> nv;
		set<vector<int>> st;
		rep(i, m + n) {
			int g = 0;
			rep(j, 3)g = gcd(g, v[i][j]);
			vector<int> cur(3);
			rep(j, 3)cur[j] = v[i][j] / g;
			if (!st.count(cur)) {
				nv.push_back(v[i]);
				st.insert(cur);
			}
		}
		swap(v, nv);
		n = v.size();
		sort(all(v));
	}
	assert(n >= 2);
	vector<pair<LDP, int>> vtp;
	vector<ld> rr(n);
	rep(i, n) {
		rr[i] = sqrt(v[i][0] * v[i][0] + v[i][1] * v[i][1] + v[i][2] * v[i][2]);
		vtp.push_back({ {v[i][0] / rr[i],v[i][1] / rr[i]},i });
	}
	sort(all(vtp));
	auto calc = [&](int i, int j) {
		ld res = 0;
		rep(k, 3)res += (v[i][k]/rr[i] - v[j][k]/rr[j]) * (v[i][k]/rr[i] - v[j][k]/rr[j]);
		return res;
	};
	ld ans = mod;
	P ansp = { -1,-1 };
	function<ld(int, int)> yaru = [&](int l, int r)->ld {
		ld mi = mod;
		if (l + 1 == r)return mod;
		int m = (l + r) / 2;
		chmin(mi, yaru(l, m));
		chmin(mi, yaru(m, r));
		ld res = mi;
		ld t = vtp[m - 1].first.first;
		vector<pair<ld, int>> vl, vr;
		Rep(i, l, m) {
			ld dx = t - vtp[i].first.first;
			if (dx*dx > ans + (1e-8))continue;
			vl.push_back({ vtp[i].first.second,vtp[i].second });
		}
		Rep(i, m, r) {
			ld dx = t - vtp[i].first.first;
			if (dx * dx > ans + (1e-8))continue;
			vr.push_back({ vtp[i].first.second,vtp[i].second });
		}
		sort(all(vl));
		sort(all(vr));
		int locl = 0;
		int locr = 0;
		//[locl,locr)
		rep(i, vl.size()) {
			while (locl < vr.size() && vr[locl].first < vl[i].first) {
				ld dy = vl[i].first - vr[locl].first;
				if (dy * dy > ans + (1e-8))locl++;
				else break;
			}
			while (locr < vr.size()) {
				if (vr[locr].first < vl[i].first)locr++;
				else {
					ld dy = vr[locr].first - vl[i].first;
					if (dy * dy > ans + (1e-8))break;
					else locr++;
				}
			}
			assert(locl <= locr);
			Rep(j, locl, locr) {
				ld val = calc(vl[i].second,vr[j].second);
				P p = minmax(vl[i].second, vr[j].second);
				if (abs(ans - val) < (1e-12)) {
					ansp = min(ansp, p);
				}
				else if (ans > val) {
					ans = val;
					ansp = p;
				}
				res = min(res, val);
			}
		}
		return res;
	};
	yaru(0, n);
	assert(ansp.first >= 0);
	vector<int> anss;
	rep(j, 3) {
		anss.push_back(v[ansp.first][j]);
	}
	rep(j, 3) {
		anss.push_back(v[ansp.second][j]);
	}
	coutarray(anss);
}


signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	while (cin >> m >> n >> s >> w, m + n)
		solve();
	return 0;
}
accuracy: 1
time_ms: 1510
memory_kb: 26936
final_rank: 4

code_snippet: #pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
#include<chrono>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;

#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);

template<typename T>
void chmin(T& a, T b) {
	a = min(a, b);
}
template<typename T>
void chmax(T& a, T b) {
	a = max(a, b);
}
template<typename T>
void cinarray(vector<T>& v) {
	rep(i, v.size())cin >> v[i];
}
template<typename T>
void coutarray(vector<T>& v) {
	rep(i, v.size()) {
		if (i > 0)cout << " "; cout << v[i];
	}
	cout << "\n";
}
ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	if (x == 0)return 0;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	int n;
	modint() :n(0) { ; }
	modint(ll m) {
		if (m < 0 || mod <= m) {
			m %= mod; if (m < 0)m += mod;
		}
		n = m;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 20;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

ll gcd(ll a, ll b) {
	a = abs(a); b = abs(b);
	if (a < b)swap(a, b);
	while (b) {
		ll r = a % b; a = b; b = r;
	}
	return a;
}

int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };




int m, n, s, w;
void solve() {
	vector<vector<int>> v(m + n);
	rep(i, m) {
		v[i].resize(3);
		rep(j, 3)cin >> v[i][j];
	}
	int g = s;
	rep(i, n) {
		v[i + m].resize(3);
		v[i + m][0] = (g / 7) % 100 + 1;
		v[i + m][1] = (g / 700) % 100 + 1;
		v[i + m][2] = (g / 70000) % 100 + 1;
		if (g % 2 == 0)g /= 2;
		else g = (g / 2) ^ w;
	}
	//erase same vector
	{
		vector<vector<int>> nv;
		set<vector<int>> st;
		rep(i, m + n) {
			int g = 0;
			rep(j, 3)g = gcd(g, v[i][j]);
			vector<int> cur(3);
			rep(j, 3)cur[j] = v[i][j] / g;
			if (!st.count(cur)) {
				nv.push_back(v[i]);
				st.insert(cur);
			}
		}
		swap(v, nv);
		n = v.size();
		sort(all(v));
	}
	assert(n >= 2);
	vector<pair<LDP, int>> vtp;
	vector<ld> rr(n);
	rep(i, n) {
		rr[i] = sqrt(v[i][0] * v[i][0] + v[i][1] * v[i][1] + v[i][2] * v[i][2]);
		vtp.push_back({ {v[i][0] / rr[i],v[i][1] / rr[i]},i });
	}
	sort(all(vtp));
	auto calc = [&](int i, int j) {
		ld res = 0;
		rep(k, 3)res += (v[i][k]/rr[i] - v[j][k]/rr[j]) * (v[i][k]/rr[i] - v[j][k]/rr[j]);
		return res;
	};
	ld ans = mod;
	P ansp = { -1,-1 };
	function<ld(int, int)> yaru = [&](int l, int r)->ld {
		ld mi = mod;
		if (l + 1 == r)return mod;
		int m = (l + r) / 2;
		chmin(mi, yaru(l, m));
		chmin(mi, yaru(m, r));
		ld res = mi;
		ld t = vtp[m - 1].first.first;
		vector<pair<ld, int>> vl, vr;
		Rep(i, l, m) {
			ld dx = t - vtp[i].first.first;
			if (dx*dx > ans + (1e-8))continue;
			vl.push_back({ vtp[i].first.second,vtp[i].second });
		}
		Rep(i, m, r) {
			ld dx = t - vtp[i].first.first;
			if (dx * dx > ans + (1e-8))continue;
			vr.push_back({ vtp[i].first.second,vtp[i].second });
		}
		sort(all(vl));
		sort(all(vr));
		//cout << "! " << l << " " << r << " " << vl.size() << " " << vr.size() << "\n";
		int locl = 0;
		int locr = 0;
		//[locl,locr)
		rep(i, vl.size()) {
			while (locl < vr.size() && vr[locl].first < vl[i].first) {
				ld dy = vl[i].first - vr[locl].first;
				if (dy * dy > ans + (1e-8))locl++;
				else break;
			}
			while (locr < vr.size()) {
				if (vr[locr].first < vl[i].first)locr++;
				else {
					ld dy = vr[locr].first - vl[i].first;
					if (dy * dy > ans + (1e-8))break;
					else locr++;
				}
			}
			assert(locl <= locr);
			Rep(j, locl, locr) {
				ld val = calc(vl[i].second,vr[j].second);
				P p = minmax(vl[i].second, vr[j].second);
				if (abs(ans - val) < (1e-12)) {
					ansp = min(ansp, p);
				}
				else if (ans > val) {
					ans = val;
					ansp = p;
				}
				res = min(res, val);
			}
		}
		return res;
	};
	yaru(0, n);
	assert(ansp.first >= 0);
	vector<int> anss;
	rep(j, 3) {
		anss.push_back(v[ansp.first][j]);
	}
	rep(j, 3) {
		anss.push_back(v[ansp.second][j]);
	}
	//cout << "ans is ";
	coutarray(anss);
	/*int id1 = -1;
	rep(i, v.size())if (v[i] == vector<int>{42, 40, 46})id1 = i;
	int id2 = -1;
	rep(i, v.size())if (v[i] == vector<int>{83, 79, 91})id2 = i;
	cout << ans << " " << calc(id1,id2) << "\n";
	cout << "! " << id1 << " " << id2 << "\n";*/
}


signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(10);
	//init_f();
	//init();
	//while(true)
	//expr();
	//init();
	//int t; cin >> t; rep(i, t)
	while (cin >> m >> n >> s >> w, m + n)
		solve();
	return 0;
}
accuracy: 1
time_ms: 1510
memory_kb: 35164
final_rank: 5

code_snippet: #pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
#include<chrono>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;

#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);

template<typename T>
void chmin(T& a, T b) {
	a = min(a, b);
}
template<typename T>
void chmax(T& a, T b) {
	a = max(a, b);
}
template<typename T>
void cinarray(vector<T>& v) {
	rep(i, v.size())cin >> v[i];
}
template<typename T>
void coutarray(vector<T>& v) {
	rep(i, v.size()) {
		if (i > 0)cout << " "; cout << v[i];
	}
	cout << "\n";
}
ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	if (x == 0)return 0;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	int n;
	modint() :n(0) { ; }
	modint(ll m) {
		if (m < 0 || mod <= m) {
			m %= mod; if (m < 0)m += mod;
		}
		n = m;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 20;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

ll gcd(ll a, ll b) {
	a = abs(a); b = abs(b);
	if (a < b)swap(a, b);
	while (b) {
		ll r = a % b; a = b; b = r;
	}
	return a;
}

int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };




int m, n, s, w;
void solve() {
	vector<vector<int>> v(m + n);
	rep(i, m) {
		v[i].resize(3);
		rep(j, 3)cin >> v[i][j];
	}
	int g = s;
	rep(i, n) {
		v[i + m].resize(3);
		v[i + m][0] = (g / 7) % 100 + 1;
		v[i + m][1] = (g / 700) % 100 + 1;
		v[i + m][2] = (g / 70000) % 100 + 1;
		if (g % 2 == 0)g /= 2;
		else g = (g / 2) ^ w;
	}
	//erase same vector
	{
		vector<vector<int>> nv;
		set<vector<int>> st;
		rep(i, m + n) {
			int g = 0;
			rep(j, 3)g = gcd(g, v[i][j]);
			vector<int> cur(3);
			rep(j, 3)cur[j] = v[i][j] / g;
			if (!st.count(cur)) {
				nv.push_back(v[i]);
				st.insert(cur);
			}
		}
		swap(v, nv);
		n = v.size();
		sort(all(v));
	}
	assert(n >= 2);
	//rep(i, n)coutarray(v[i]);
	vector<LDP> vt(n);
	rep(i, n) {
		vt[i] = { atan2l(v[i][1],v[i][0]),atan2l(v[i][2],sqrt(v[i][0] * v[i][0] + v[i][1] * v[i][1])) };
	}
	vector<pair<LDP, int>> vtp;
	rep(i, n) {
		vtp.push_back({ vt[i],i });
	}
	sort(all(vtp));
	auto trans = [&](LDP a, ld& x, ld& y, ld& z) {
		z = sin(a.second);
		ld xy = cos(a.second);
		x = xy * cos(a.first);
		y = xy * sin(a.first);
	};
	auto calc = [&](LDP a, LDP b) {
		ld x1, y1, z1, x2, y2, z2;
		trans(a, x1, y1, z1);
		trans(b, x2, y2, z2);
		return (x1 * x2 + y1 * y2 + z1 * z2) / sqrt(x1 * x1 + y1 * y1 + z1 * z1) / sqrt(x2 * x2 + y2 * y2 + z2 * z2);
	};
	ld ans = 0;
	P ansp = { -1,-1 };
	function<ld(int, int)> yaru = [&](int l, int r)->ld {
		ld ma = 0;
		if (l + 1 == r)return 0;
		int m = (l + r) / 2;
		chmax(ma, yaru(l, m));
		chmax(ma, yaru(m, r));
		ld res = ma;
		ld t = vt[m - 1].first;
		vector<pair<ld, int>> vl, vr;
		Rep(i, l, m) {
			LDP mirr = { t,vt[i].second };
			if (calc(mirr, vt[i]) < ma - (1e-0))continue;
			//if (l == 0 &&r == n)cout << "!! " << i << "\n";
			vl.push_back({ vt[i].second,i });
		}
		Rep(i, m, r) {
			LDP mirr = { t,vt[i].second };
			if (calc(mirr, vt[i]) < ma - (1e-0))continue;
			vr.push_back({ vt[i].second,i });
			//if (l == 0 && r == n)cout << "!! " << i << "\n";
		}
		sort(all(vl));
		sort(all(vr));
		//cout << "! " << l << " " << r << " " << vl.size() << " " << vr.size() << "\n";
		int locl = 0;
		int locr = 0;
		//[locl,locr)
		rep(i, vl.size()) {
			LDP cur = vt[vl[i].second];
			while (locl < vr.size() && vr[locl].first < vl[i].first) {
				LDP mirr = cur; mirr.second = vr[locl].first;
				if (calc(mirr, cur) < ma - (1e-8))locl++;
				else break;
			}
			while (locr < vr.size()) {
				if (vr[locr].first < vl[i].first)locr++;
				else {
					LDP mirr = cur; mirr.second = vr[locr].first;
					if (calc(mirr, cur) < ma - (1e-8))break;
					else locr++;
				}
			}
			assert(locl <= locr);
			Rep(j, locl, locr) {
				ld val = calc(cur, vt[vr[j].second]);
				P p = { vl[i].second,vr[j].second };
				if (p.first > p.second)swap(p.first, p.second);
				//cout << "!! " << p.first << " " << p.second << "\n";
				if (abs(ans - val) < (1e-12)) {
					ansp = min(ansp, p);
				}
				else if (ans < val) {
					ans = val;
					ansp = p;
				}
				res = max(res, val);
			}
		}
		return res;
	};
	yaru(0, n);
	assert(ansp.first >= 0);
	vector<int> anss;
	rep(j, 3) {
		anss.push_back(v[ansp.first][j]);
	}
	rep(j, 3) {
		anss.push_back(v[ansp.second][j]);
	}
	//cout << "ans is ";
	coutarray(anss);
	/*int id1 = -1;
	rep(i, v.size())if (v[i] == vector<int>{42, 40, 46})id1 = i;
	int id2 = -1;
	rep(i, v.size())if (v[i] == vector<int>{83, 79, 91})id2 = i;*/
	//cout << ans << " " << calc(vt[id1], vt[id2]) << "\n";
	//cout << "! " << id1 << " " << id2 << "\n";
}


signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(10);
	//init_f();
	//init();
	//while(true)
	//expr();
	//init();
	//int t; cin >> t; rep(i, t)
	while (cin >> m >> n >> s >> w, m + n)
		solve();
	return 0;
}
accuracy: 1
time_ms: 5280
memory_kb: 35448
final_rank: 13

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
//#define EPS 0.000000001
using namespace std;

#define EPS 0.0000001
#define NUM 120005

struct Info{

	bool operator<(const struct Info &arg) const{
		return angle < arg.angle;
	}
	ll x,y,z;
	double angle;
};


int N;
Info info[NUM];


double calc_angle(Info A,Info B){

	double bunshi = A.x*B.x+A.y*B.y+A.z*B.z;
	double bunbo = sqrt(A.x*A.x+A.y*A.y+A.z*A.z)*sqrt(B.x*B.x+B.y*B.y+B.z*B.z);

	return acos(bunshi/bunbo);
}

bool compare(Info A,Info B){

	if(A.x != B.x){

		return A.x < B.x;

	}else if(A.y != B.y){

		return A.y < B.y;

	}else if(A.z != B.z){

		return A.z < B.z;
	}
	return -1;
}

bool isSame(Info A,Info B){

	return A.x == B.x && A.y == B.y && A.z == B.z;
}

void func(){


	Info base;
	base.x = 1;
	base.y = 1;
	base.z = 1;

	for(int i = 0; i < N; i++){

		info[i].angle = calc_angle(base,info[i]);
	}

	sort(info,info+N);

	Info ans_L,ans_R;

	double minimum = acos(0);
	double tmp_angle;

	for(int i = 0; i < N-1; i++){
		for(int k = i+1; k < N; k++){
			if(fabs(info[i].angle - info[k].angle) > minimum) break;

			tmp_angle = calc_angle(info[i],info[k]);
			if(tmp_angle < EPS)continue;

			if(tmp_angle+EPS < minimum){
				minimum = tmp_angle;

				if(compare(info[i],info[k])){

					ans_L = info[i];
					ans_R = info[k];

				}else{

					ans_L = info[k];
					ans_R = info[i];
				}

			}else if(fabs(tmp_angle-minimum) < EPS){

				if(compare(info[i],info[k])){

					if((compare(info[i],ans_L) == true) || (isSame(info[i],ans_L) && compare(info[k],ans_R) == true)){

						ans_L = info[i];
						ans_R = info[k];
					}

				}else{

					if((compare(info[k],ans_L) == true) || (isSame(info[k],ans_L) && compare(info[i],ans_R) == true)){

						ans_L = info[k];
						ans_R = info[i];
					}
				}
			}
		}
	}

	printf("%lld %lld %lld %lld %lld %lld\n",ans_L.x,ans_L.y,ans_L.z,ans_R.x,ans_R.y,ans_R.z);
}

int main(){

	ll num_1,num_2,S,W;

	while(true){

		scanf("%lld %lld %lld %lld",&num_1,&num_2,&S,&W);
		if(num_1 == 0 && num_2 == 0 && S == 0 && W == 0)break;

		for(int i = 0; i < num_1; i++){

			scanf("%lld %lld %lld",&info[i].x,&info[i].y,&info[i].z);
		}

		ll g = S;

		for(int i = 0; i < num_2; i++){
			info[i+num_1].x = (g/7)    %100 + 1;
			info[i+num_1].y = (g/700)  %100 + 1;
			info[i+num_1].z = (g/70000)%100 + 1;
			if( g%2 == 0 ) { g = (g/2); }
			else           { g = (g/2) ^ W; }
		}

		N = num_1+num_2;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 1010
memory_kb: 6756
final_rank: 2

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <map>
using namespace std;
const double EPS = 1e-8;
const double INF = 1e18;

bool epsleq(const double &a, const double &b){
    return a +EPS < b;
}
bool epseq(const double &a, const double &b){
    return abs(a-b) < EPS;
}

struct Point{
    double x,y,z;
    Point(double x, double y, double z):x(x), y(y), z(z){}
    Point(){}
    Point &operator +=(const Point &a){ x+=a.x; y+=a.y; z+=a.z; return *this; }
    Point &operator -=(const Point &a){ x-=a.x; y-=a.y; z-=a.z; return *this; }
    Point &operator *=(const double &a){ x*=a; y*=a; z*=a; return *this; }
    Point operator +(const Point &a) const{ return Point(x+a.x, y+a.y, z+a.z); }
    Point operator -(const Point &a) const{ return Point(x-a.x, y-a.y, z-a.z); }
    Point operator *(const double &a) const{ return Point(a*x, a*y, a*z); }
    Point operator -() { return Point(-x, -y, -z); }
    bool operator <(const Point &a) const{
        return !epseq(x, a.x)? x < a.x: !epseq(y, a.y)? y < a.y: epsleq(z, a.z);
    }
    bool operator ==(const Point &a) const{
        double dx=x-a.x, dy=y-a.y, dz=z-a.z;
        return sqrt(dx*dx +dy*dy +dz*dz) < EPS;
    }
};

double dot(const Point &a, const Point &b){
    return a.x*b.x +a.y*b.y +a.z*b.z;
}
Point cross(const Point &a, const Point &b){
    return Point(a.y*b.z -a.z*b.y, a.z*b.x -a.x*b.z, a.x*b.y -a.y*b.x);
}
double abs(const Point &a){
    return sqrt(dot(a, a));
}
Point unit(const Point &a){
    return a *(1/abs(a));
}

bool ycomp(const Point &a, const Point &b){
    return !epseq(a.y, b.y)? a.y < b.y: !epseq(a.x, b.x)? a.x < b.x: epsleq(a.z, b.z);
}
bool dpcomp(const pair<double, pair<Point, Point> > &a, const pair<double, pair<Point, Point> > &b){
    return !epseq(a.first, b.first)? a.first < b.first : a.second < b.second;
}

pair<double, pair<Point, Point> > closest(vector<Point> &v, int first, int last, map<Point, Point> &conv){
    if(last -first <= 1) return make_pair(INF, make_pair(Point(), Point()));
    int mid = (first +last)/2;
    double midx = v[mid].x;
    pair<double, pair<Point, Point> > cp = min(closest(v, first, mid, conv), closest(v, mid, last, conv), dpcomp);
    inplace_merge(v.begin()+first, v.begin()+mid, v.begin()+last, ycomp);
    
    vector<Point> near;
    for(int i=first; i<last; i++){
        if(abs(v[i].x -midx) > cp.first +EPS) continue;
        for(int j=near.size()-1; j>=0; j--){
            if(abs(v[i].y -near[j].y) > cp.first +EPS){
                break;
            }
            pair<double, pair<Point, Point> > ncp(abs(v[i] -near[j]), pair<Point, Point>(conv[v[i]], conv[near[j]]));
            if(ncp.second.second < ncp.second.first) swap(ncp.second.first, ncp.second.second);
            cp = min(cp, ncp, dpcomp);
        }
        near.push_back(v[i]);
    }
    return cp;
}

int main(){
    while(1){
        int m,n,s,w;
        cin >> m >> n >> s >> w;
        if(m==0 && n==0) break;

        vector<Point> v(m+n);
        for(int i=0; i<m; i++){
            cin >> v[i].x >> v[i].y >> v[i].z;
        }
        for(int i=m; i<m+n; i++){
            v[i].x = (s/7) %100 +1;
            v[i].y = (s/700) %100 +1;
            v[i].z = (s/70000) %100 +1;
            if(s%2 == 0){
                s = s/2;
            }else{
                s = (s/2) ^ w;
            }
        }

        n += m;
        map<Point, Point> conv;
        for(int i=0; i<n; i++){
            Point univec = unit(v[i]);
            if(conv.count(univec) == 0){
                conv[univec] = v[i];
            }else{
                conv[univec] = min(conv[univec], v[i]);
            }
        }

        vector<Point> uni;
        for(pair<Point, Point> pp: conv){
            uni.push_back(pp.first);
        }
        pair<double, pair<Point, Point> > ret = closest(uni, 0, uni.size(), conv);
        Point &a = ret.second.first;
        Point &b = ret.second.second;
        cout << fixed << setprecision(0);
        cout << a.x << " " << a.y << " " << a.z << " ";
        cout << b.x << " " << b.y << " " << b.z << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 1750
memory_kb: 19516
final_rank: 3

code_snippet: // AOJ 1340: Directional Resemblence
#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;
int n, m, S, W, px[120009], py[120009], pz[120009], p[120009]; long double x[120009], y[120009], z[120009];
int main() {
	while(scanf("%d %d %d %d", &n, &m, &S, &W), n + m != 0) {
		for(int i = 0; i < n; ++i) {
			scanf("%d %d %d", &px[i], &py[i], &pz[i]);
		}
		for(int i = n; i < n + m; ++i) {
			px[i] = S / 7 % 100 + 1;
			py[i] = S / 700 % 100 + 1;
			pz[i] = S / 70000 % 100 + 1;
			if(S & 1) S = (S >> 1) ^ W;
			else S >>= 1;
		}
		n += m;
		for(int i = 0; i < n; ++i) {
			long double d = sqrt((long double)(px[i] * px[i] + py[i] * py[i] + pz[i] * pz[i]));
			x[i] = px[i] / d;
			y[i] = py[i] / d;
			z[i] = pz[i] / d;
			p[i] = i;
		}
		sort(p, p + n, [](int i, int j) {
			if(abs(x[i] - x[j]) > 1.0e-12L) return x[i] < x[j];
			if(abs(y[i] - y[j]) > 1.0e-12L) return y[i] < y[j];
			if(abs(z[i] - z[j]) > 1.0e-12L) return z[i] < z[j];
			if(px[i] != px[j]) return px[i] < px[j];
			if(py[i] != py[j]) return py[i] < py[j];
			return pz[i] < pz[j];
		});
		long double ans = 1.0e+9;
		int pa = -1, pb = -1, r = 0;
		for(int i = 0; i < n; ++i) {
			while(r != n && abs(x[p[i]] - x[p[r]]) < 1.0e-12L && abs(y[p[i]] - y[p[r]]) < 1.0e-12L && abs(z[p[i]] - z[p[r]]) < 1.0e-12) ++r;
			for(int j = r; j < n && (x[p[j]] - x[p[i]]) * (x[p[j]] - x[p[i]]) < ans - 1.0e-12L; ++j) {
				long double d = (x[p[i]] - x[p[j]]) * (x[p[i]] - x[p[j]]) + (y[p[i]] - y[p[j]]) * (y[p[i]] - y[p[j]]) + (z[p[i]] - z[p[j]]) * (z[p[i]] - z[p[j]]);
				if(d < ans - 1.0e-16L) {
					ans = d;
					pa = p[i];
					pb = p[j];
				}
			}
		}
		int ax = px[pa], ay = py[pa], az = pz[pa], bx = px[pb], by = py[pb], bz = pz[pb];
		if(ax > bx || (ax == bx && (ay > by || (ay == by && az > bz)))) {
			swap(ax, bx);
			swap(ay, by);
			swap(az, bz);
		}
		printf("%d %d %d %d %d %d\n", ax, ay, az, bx, by, bz);
	}
	return 0;
}
accuracy: 1
time_ms: 350
memory_kb: 9028
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll=long long;
#define rep(i,n) for(int i=0;i<n;i++)
#define all(a) a.begin(),a.end()

const double EPS=1E-15;
constexpr int gcd(int a,int b){return b?gcd(b,a%b):a;}

struct v{
	int x,y,z,g;
	double L2,nx,ny,nz;
	bool operator==(const v&r)const{return this->x==r.x and this->y==r.y and this->z==r.z and this->g==r.g;};
	void setData(){
	    g=gcd(x,gcd(y,z));
        L2=sqrt(x*x+y*y+z*z)/g;
        nx=x/g/L2;
        ny=y/g/L2;
        nz=z/g/L2;
	}
	friend ostream& operator<<(ostream&os,const v&p);
};

bool operator<(const v&l,const v&r){return l.nx<r.nx or (l.nx==r.nx and (l.ny<r.ny or (l.ny==r.ny and l.nz<r.nz)));};
ostream& operator<<(ostream&os, const v&p){os<<p.x<<" "<<p.y<<" "<<p.z; return os;};

v makeData(int X, int Y, int Z){
	v ret;
	ret.x=X, ret.y=Y, ret.z=Z;
	ret.setData();
	return ret;
}

bool same(v a,v b){
    return a.x/a.g==b.x/b.g and a.y/a.g==b.y/b.g and a.z/a.g==b.z/b.g;
}

bool cmp(v a,v b){
	return a.x<b.x or (b.x==a.x and (a.y<b.y or (b.y==a.y and a.z<b.z)));
}

double dist(v a, v b){
    if(same(a,b)) return 10000; 
    return sqrt((b.nx-a.nx)*(b.nx-a.nx) + (b.ny-a.ny)*(b.ny-a.ny) + (b.nz-a.nz)*(b.nz-a.nz));
}


using data=pair<double,pair<v,v>>;
data closest_pair(vector<v> vec){
    if(vec.size()<=1) return {10000,{v(),v()}};
    if(vec.size()==2){
		if(cmp(vec[1],vec[0])){
			//cout<<"Ret (2) :"<<vec[1]<<" "<<vec[0]<<" = "<<dist(vec[0],vec[1])<<endl;
			return {dist(vec[0],vec[1]),{vec[1],vec[0]}};
		}else{
			//cout<<"Ret (2) :"<<vec[0]<<" "<<vec[1]<<" = "<<dist(vec[0],vec[1])<<endl;
			return {dist(vec[0],vec[1]),{vec[0],vec[1]}};
		}
	}
    vector<v> vs1,vs2,vs3;
    int index=vec.size()/2;
    double sep=vec[index].nx;
    copy(vec.begin(), vec.begin()+index, back_inserter(vs1));
    copy(vec.begin()+index, vec.end(), back_inserter(vs2));
    
	data s1=closest_pair(vs1), s2=closest_pair(vs2), minDist;
	if(fabs(s1.first-s2.first)>EPS){
		minDist=min(s1,s2);
	}else{
		if(cmp(s1.second.first,s2.second.first) or (s1.second.first==s2.second.first and cmp(s1.second.second,s2.second.second))){
			minDist=s1;
		}else{
			minDist=s2;
		}
	}
    
    sort(all(vec),[](v a,v b){return a.ny<b.ny;});
    
    for(auto d:vec){
        if(fabs(d.nx-sep)>=minDist.first) continue;
        for(int i=vs3.size()-1;i>=0;i--){
            double dst=dist(vs3[i],d);
			//if(dst>minDist.first)break;
			v n1=vs3[i],n2=d;
			if(cmp(n2,n1))swap(n1,n2);
			if(fabs(minDist.first-dst)<EPS){
				if(cmp(n1,minDist.second.first) or (n1==minDist.second.first and cmp(n2,minDist.second.second))){
					//cout<<"   "<<n1<<" "<<n2<<endl;
					minDist={dst,{n1,n2}};
				}
			}else if(dst<minDist.first){
				//cout<<"   "<<n1<<" "<<n2<<endl;
                minDist={dst,{n1,n2}};
            }
        }
        vs3.push_back(d);
    }
	//cout<<"Ret ("<<vec.size()<<") :"<<minDist.second.first<<" "<<minDist.second.second<<" = "<<minDist.first<<endl;
    return minDist;
    
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	
	int m,n,s,w;
	while(cin>>m>>n>>s>>w, m or n){
		vector<v> vec;
		rep(i,m){
			int x,y,z;
			cin>>x>>y>>z;
			vec.push_back(makeData(x,y,z));
		}
		int g=s;
		rep(i,n) {
			vec.push_back(makeData((g/7)%100+1, (g/700)%100+1, (g/70000)%100+1));
			if(g%2==0)g/=2;
			else g=(g/2) xor w;
		}
	    sort(all(vec),[](v a,v b){return a.nx<b.nx;});
		vec.erase(unique(all(vec),same),vec.end());
		//for(auto d:vec)cout<<d<<"("<<d.nx<<")"<<endl;
		//cout<<"===="<<endl;
	    data ans=closest_pair(vec);
	    v a1=ans.second.first;
	    v a2=ans.second.second;
	    if(cmp(a2,a1)) swap(a1,a2);
	    cout<<a1<<" "<<a2<<endl;
	}
	return 0;
}
accuracy: 1
time_ms: 3860
memory_kb: 25824
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ld = long double;
#define rep(i, j) for(int i=0; i < (int)(j); i++)
#define all(v) v.begin(),v.end()
const ld EPS = 1e-8;
bool eq(ld a, ld b) { return abs(a - b) < EPS; }

template<class T>
struct Point {
    T x, y, z;
    bool operator < (const Point<T> &r) const { return make_tuple(x, y, z) < make_tuple(r.x, r.y, r.z); }
};

template<class T>
ld length(const Point<T> &p) {
    return sqrtl(p.x * p.x + p.y * p.y + p.z * p.z);
}
template<class T>
ld dot(const Point<T> &a, const Point<T> &b) {
    return a.x * b.x + a.y * b.y + a.z * b.z;
}
template<class T>
ld angle(const Point<T> &a, const Point<T> &b) {
    return acosl(dot(a, b) / length(a) / length(b));
}
template<class T>
Point<ld> unit(Point<T> a) {
    Point<ld> p = {(ld)a.x, (ld)a.y, (ld)a.z};
    ld l = length(p);
    p.x /= l;
    p.y /= l;
    p.z /= l;
    return p;
}

bool solve() {
    using PI = Point<int>;
    int m, n, S, W; cin >> m >> n >> S >> W;
    if(m == 0 and n == 0 and S == 0 and W == 0) return false;
    vector<PI> V(m + n);
    rep(i, m) cin >> V[i].x >> V[i].y >> V[i].z;
    { // generate
        int g = S;
        for(int i=m; i<m+n; i++) {
            V[i].x = (g/7)    %100 + 1;
            V[i].y = (g/700)  %100 + 1;
            V[i].z = (g/70000)%100 + 1;
            if( g%2 == 0 ) { g = (g/2); }
            else           { g = (g/2) ^ W; }
        }
    }
    sort(all(V), [&] (PI a, PI b) { return unit(a).x > unit(b).x; });
    
    ld min_angle = 1e9;    
    PI a, b;

    auto need_check = [&] (PI &a, PI &b) {
        ld alpha = acosl(unit(a).x);
        return cosl(alpha + min_angle) < unit(b).x + EPS;
    };
    
    queue<PI> que;
    rep(i, V.size()) {
        queue<PI> nxt_que;
        while(que.size()) {
            auto p = que.front(); que.pop();
            if(not need_check(p, V[i])) continue;
            ld ang = angle(V[i], p);
            if(ang > EPS) {
                if(min_angle + EPS > ang) {                    
                    auto va = V[i], vb = p;
                    if(vb < va) swap(va, vb);
                    if(!eq(min_angle, ang) or make_pair(a, b) > make_pair(va, vb)) {
                        a = va;
                        b = vb;
                    }
                    min_angle = ang;
                }
            }
            nxt_que.push(p);
        }
        nxt_que.push(V[i]);
        swap(que, nxt_que);
    }
    printf("%d %d %d %d %d %d\n", a.x, a.y, a.z, b.x, b.y, b.z);
    return true;
}

int main() {
    while(solve());
    return 0;
}
accuracy: 1
time_ms: 5290
memory_kb: 4748
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;

using pii = pair<int,int>;
using ll = long long;
using ld = long double;
#define rep(i, j) for(int i=0; i < (int)(j); i++)
#define repeat(i, j, k) for(int i = (j); i < (int)(k); i++)
#define all(v) v.begin(),v.end()
#define debug(x) cerr << #x << " : " << x << endl

template<class T> bool set_min(T &a, const T &b) { return a > b  ? a = b, true : false; }
template<class T> bool set_max(T &a, const T &b) { return a < b  ? a = b, true : false; }
// vector
template<class T> istream&
operator >> (istream &is , vector<T> &v) { for(T &a : v) is >> a; return is; }
template<class T> ostream&
operator << (ostream &os , const vector<T> &v) { for(const T &t : v) os << "\t" << t; return os << endl; }
// pair
template<class T, class U> ostream&
operator << (ostream &os , const pair<T, U> &v) { return os << "<" << v.first << ", " << v.second << ">"; }

const int INF = 1 << 30;
const ll INFL = 1LL << 60;
const ld EPS = 1e-9;
bool eq(ld a, ld b) { return abs(a - b) < EPS; }
template<class T>
struct Point {
    T x, y, z;
    bool operator < (const Point<T> &r) const {
        return make_tuple(x, y, z) < make_tuple(r.x, r.y, r.z);
    }
};
template<class T>
ld length(const Point<T> &p) { return sqrtl(p.x * p.x + p.y * p.y + p.z * p.z); }
template<class T>
ld dot(const Point<T> &a, const Point<T> &b) { return a.x * b.x + a.y * b.y + a.z * b.z; }
template<class T>
ld angle(const Point<T> &a, const Point<T> &b) {
    return acosl(dot(a, b) / length(a) / length(b));
}
template<class T>
Point<ld> unit(Point<T> a) {
    Point<ld> p = {(ld)a.x, (ld)a.y, (ld)a.z};
    ld l = length(p);
    p.x /= l;
    p.y /= l;
    p.z /= l;
    return p;
}

bool solve() {
    int m, n, S, W; cin >> m >> n >> S >> W;
    if(m == 0 and n == 0 and S == 0 and W == 0) return false;
    vector<Point<int>> VI(m + n);
    rep(i, m) {
        cin >> VI[i].x >> VI[i].y >> VI[i].z;
    }
    int g = S;
    for(int i=m; i<m+n; i++) {
        VI[i].x = (g/7)    %100 + 1;
        VI[i].y = (g/700)  %100 + 1;
        VI[i].z = (g/70000)%100 + 1;
        if( g%2 == 0 ) { g = (g/2); }
        else           { g = (g/2) ^ W; }
    }
    sort(all(VI), [&] (Point<int> a, Point<int> b) {
            return unit(a).x > unit(b).x;
        });
    ld min_angle = 1e9;    
    Point<int> a, b;

    auto need_check = [&] (Point<int> &a, Point<int> &b) {
        ld alpha = acosl(unit(a).x);
        auto ss = cosl(alpha + min_angle);
        auto tt = unit(b).x;
        // cerr << ss << " " << tt << endl;
        return ss < tt + EPS*10;
    };
    
    queue<Point<int>> que;
    rep(i, VI.size()) {
        queue<Point<int>> nxt_que;
        while(que.size()) {
            auto p = que.front(); que.pop();
            if(not need_check(p, VI[i])) continue;
            ld ang = angle(VI[i], p);
            if(ang > EPS) {
                if(min_angle + EPS > ang) {                    
                    auto aa = VI[i], bb = p;
                    if(bb < aa) swap(aa, bb);
                    if(!eq(min_angle, ang) or make_pair(a, b) > make_pair(aa, bb)) {
                        a = aa;
                        b = bb;
                    }
                    min_angle = ang;
                }
            }
            nxt_que.push(p);
        }
        nxt_que.push(VI[i]);
        swap(que, nxt_que);
    }
    printf("%d %d %d %d %d %d\n",
           a.x, a.y, a.z,
           b.x, b.y, b.z);
    return true;
}

int main() {
    while(solve());
    return 0;
}
accuracy: 1
time_ms: 5310
memory_kb: 4572
final_rank: 6

code_snippet: #include "bits/stdc++.h"
using namespace std;
using ld = long double;
const ld eps = 1e-9;

ld getdis(vector<ld>&l, vector<ld>&r) {
	ld sum = 0;
	for (int i = 0; i < 3; ++i) {
		sum += (l[i] - r[i])*(l[i] - r[i]);
	}
	return sqrt(sum);
}

struct po {
	int index;
	vector<ld> coors;
	po(int _d) :coors(_d) {
		index = -1;
	}
	po(int _index, vector<ld>_coors) :index(_index), coors(_coors) {

	}
	po() {}
};
ld getdis(po&lpo, po&rpo) {
	return getdis(lpo.coors, rpo.coors);
}
template<class T>
class axisSorter {
	int k;
public:
	axisSorter(int _k) : k(_k) {}
	bool operator()(const T &a, const T &b) {
		return a.coors[k] < b.coors[k];
	}
};



struct Ans {
	ld dis;
	pair<int, int>p;

};


bool operator<(const Ans&l, const Ans&r) {
	if (abs(l.dis - r.dis) < eps) {
		assert(l.p.first < l.p.second);
		assert(r.p.first < r.p.second);
		return l.p < r.p;
	}
	else {
		return l.dis < r.dis;
	}
	return true;
}
Ans answer;

template<class T, int Dim = 3>
struct kdtree {
public:
	T midpo;
	vector<T>pos;
	shared_ptr<kdtree<T>> ltree, rtree;
	int depth;
	int axis;
	kdtree(const T &p_) :midpo(p_), ltree(), rtree() {

	}
	~kdtree() {
	}

	kdtree(vector<T>&ps_, const int& l, const int& r, const int depth_ = 0) : ltree(nullptr), rtree(nullptr), depth(depth_), axis(depth%Dim) {
		init(ps_, l, r);
	}
	void getmindis() {
		vector<po>lpos, rpos;
		ld axisvalue = midpo.coors[axis];

		if (ltree != nullptr) {
			for (auto &po : ltree->pos) {
				if (po.coors[axis]>axisvalue - sqrt(answer.dis) - eps * 10) {
					lpos.emplace_back(po);
				}
			}
		}
		if (rtree != nullptr) {
			for (auto &po : rtree->pos) {
				if (po.coors[axis]<axisvalue + sqrt(answer.dis) + eps * 10) {
					rpos.emplace_back(po);
				}
			}
		}

		for (auto& lpo : lpos) {
			for (auto& rpo : rpos) {
				ld dis = getdis(lpo, rpo);
				pair<int, int> p(rpo.index, lpo.index);
				if (p.first > p.second)swap(p.first, p.second);
				Ans nans{ dis,p };
				answer = min(answer, nans);
			}
			{
				ld dis = getdis(lpo, midpo);
				pair<int, int> p(midpo.index, lpo.index);
				if (p.first > p.second)swap(p.first, p.second);
				Ans nans{ dis,p };
				answer = min(answer, nans);
			}
		}
		for (auto& rpo : rpos) {
			ld dis = getdis(midpo, rpo);
			pair<int, int> p(midpo.index, rpo.index);
			if (p.first > p.second)swap(p.first, p.second);
			Ans nans{ dis,p };
			answer = min(answer, nans);
		}
	}
private:
	void init(vector<T>&ps, const int& l, const int& r) {
		if (l >= r) {
			return;
		}
		const int mid = (l + r) / 2;
		nth_element(ps.begin() + l, ps.begin() + mid, ps.begin() + r, axisSorter<T>(axis));
		midpo = ps[mid];

		ltree = make_kdtree(ps, l, mid, depth + 1);
		
		rtree = make_kdtree(ps, mid + 1, r, depth + 1);
		getmindis();
		ltree.reset();
		rtree.reset();
		pos = vector<T>(ps.begin() + l, ps.begin() + r);
	}
};


//[l..r)
template<class T>
unique_ptr<kdtree<T>>make_kdtree(vector<T>&ps_, const int& l, const int& r, const int& depth = 0) {
	if (l >= r)return nullptr;
	else {
		return make_unique<kdtree<T>>(ps_, l, r, depth);
	}
}

vector<ld>getunit(vector<int>v) {
	vector<ld>unit;
	ld len = 0;
	for (auto&&a : v) {
		len += a*a;
		unit.emplace_back(ld(a));
	}
	len = sqrt(len);
	for (auto&u : unit) {
		u /= len;
	}
	return unit;
}
int gcd(int l, int r) {
	assert(l > 0 && r > 0);
	if (l > r)return gcd(r, l);
	else {
		const  int num = r%l;
		if (num) {
			return gcd(l, num);
		}
		else {
			return l;
		}
	}
}
int gcd(vector<int>nums) {
	if (nums.size() == 1)return nums[0];
	int num = nums[0];

	for (int i = 1; i < nums.size(); ++i) {
		num = gcd(num, nums[i]);
	}
	return num;
}

int main() {
	while (1) {
		answer = Ans{ 1e18,make_pair(-1,-1) };
		int M, N, S, W; cin >> M >> N >> S >> W;
		if (!M&&!N&&!S&&!W)break;
		vector<po>pos;
		vector<vector<int>>memo;
		{
			{
				int nx, ny, nz;
				for (int i = 0; i < M; ++i) {
					cin >> nx >> ny >> nz;
					memo.push_back(vector<int>{nx, ny, nz});
				}
				int g = S;
				for (int i = M; i < M + N; ++i) {
					nx = (g / 7) % 100 + 1;
					ny = (g / 700) % 100 + 1;
					nz = (g / 70000) % 100 + 1;
					memo.push_back(vector<int>{nx, ny, nz});
					if (g % 2 == 0)g = g / 2;
					else g = (g / 2) ^ W;
				}
			}
			sort(memo.begin(), memo.end(), [](const vector<int>&l, const vector<int>&r) {
				for (int i = 0; i < 3; ++i) {
					if (l[i] == r[i])continue;
					else return l[i] < r[i];
				}
				return false;
			});
			{
				vector<vector<int>>newmemo;
				map<vector<int>, int>amap;
				for (int i = 0; i < memo.size(); ++i) {
					int agcd = gcd(memo[i]);
					vector<int>v(3);
					for (int j = 0; j < 3; ++j)v[j] = memo[i][j] / agcd;
					if (amap.find(v) == amap.end() || amap[v] > agcd) {
						amap[v] = agcd;
					}
				}
				for (auto m : amap) {
					auto v = m.first;
					for (int i = 0; i < 3; ++i) {
						v[i] *= m.second;
					}
					newmemo.emplace_back(v);
				}
				memo = newmemo;
			}
			sort(memo.begin(), memo.end(), [](const vector<int>&l, const vector<int>&r) {
				for (int i = 0; i < 3; ++i) {
					if (l[i] == r[i])continue;
					else return l[i] < r[i];
				}
				return false;
			});
			for (int i = 0; i < memo.size(); ++i) {
				po p(i, getunit(memo[i]));
				pos.emplace_back(p);
			}
		}

		auto tree = make_kdtree(pos, 0, pos.size(), 0);
		tree->getmindis();
		auto ansp = answer;
		if (ansp.p.first >ansp.p.second)swap(ansp.p.first, ansp.p.second);
		for (int i = 0; i < 3; ++i) {
			cout << memo[answer.p.first][i] << " ";
		}
		for (int i = 0; i < 3; ++i) {
			cout << memo[answer.p.second][i];
			if (i == 2)cout << endl;
			else cout << " ";
		}
	}
	return 0;
}
accuracy: 1
time_ms: 6290
memory_kb: 26912
final_rank: 12

code_snippet: #include "bits/stdc++.h"
using namespace std;
using ld = long double;
const ld eps = 1e-9;

ld getdis(vector<ld>&l, vector<ld>&r) {
	ld sum = 0;
	for (int i = 0; i < 3; ++i) {
		sum += (l[i] - r[i])*(l[i] - r[i]);
	}
	return sqrt(sum);
}

struct po {
	int index;
	vector<ld> coors;
	po(int _d) :coors(_d) {
		index = -1;
	}
	po(int _index, vector<ld>_coors) :index(_index), coors(_coors) {

	}
	po() {}
};
ld getdis(po&lpo, po&rpo) {
	return getdis(lpo.coors, rpo.coors);
}
template<class T>
class axisSorter {
	int k;
public:
	axisSorter(int _k) : k(_k) {}
	bool operator()(const T &a, const T &b) {
		return a.coors[k] < b.coors[k];
	}
};



struct Ans {
	ld dis;
	pair<int, int>p;

};


bool operator<(const Ans&l, const Ans&r) {
	if (abs(l.dis - r.dis) < eps) {
		assert(l.p.first < l.p.second);
		assert(r.p.first < r.p.second);
		return l.p < r.p;
	}
	else {
		return l.dis < r.dis;
	}
	return true;
}
Ans answer;

template<class T, int Dim = 3>
struct kdtree {
public:
	T midpo;
	vector<T>pos;
	shared_ptr<kdtree<T>> ltree, rtree;
	int depth;
	int axis;
	kdtree(const T &p_) :midpo(p_), ltree(), rtree() {

	}
	~kdtree() {
	}

	kdtree(vector<T>&ps_, const int& l, const int& r, const int depth_ = 0) : ltree(nullptr), rtree(nullptr), depth(depth_), axis(depth%Dim) {
		init(ps_, l, r);
	}
	void getmindis() {
		vector<po>lpos, rpos;
		ld axisvalue = midpo.coors[axis];

		if (ltree != nullptr) {
			for (auto &po : ltree->pos) {
				if (po.coors[axis]>axisvalue - sqrt(answer.dis) - eps * 10) {
					lpos.emplace_back(po);
				}
			}
		}
		if (rtree != nullptr) {
			for (auto &po : rtree->pos) {
				if (po.coors[axis]<axisvalue + sqrt(answer.dis) + eps * 10) {
					rpos.emplace_back(po);
				}
			}
		}

		for (auto& lpo : lpos) {
			for (auto& rpo : rpos) {
				ld dis = getdis(lpo, rpo);
				pair<int, int> p(rpo.index, lpo.index);
				if (p.first > p.second)swap(p.first, p.second);
				Ans nans{ dis,p };
				answer = min(answer, nans);
			}
			{
				ld dis = getdis(lpo, midpo);
				pair<int, int> p(midpo.index, lpo.index);
				if (p.first > p.second)swap(p.first, p.second);
				Ans nans{ dis,p };
				answer = min(answer, nans);
			}
		}
		for (auto& rpo : rpos) {
			ld dis = getdis(midpo, rpo);
			pair<int, int> p(midpo.index, rpo.index);
			if (p.first > p.second)swap(p.first, p.second);
			Ans nans{ dis,p };
			answer = min(answer, nans);
		}
	}
private:
	void init(vector<T>&ps, const int& l, const int& r) {
		if (l >= r) {
			return;
		}
		const int mid = (l + r) / 2;
		nth_element(ps.begin() + l, ps.begin() + mid, ps.begin() + r, axisSorter<T>(axis));
		midpo = ps[mid];

		ltree = make_kdtree(ps, l, mid, depth + 1);
		
		rtree = make_kdtree(ps, mid + 1, r, depth + 1);
		getmindis();
		ltree.reset();
		rtree.reset();
		pos = vector<T>(ps.begin() + l, ps.begin() + r);
	}
};


//[l..r)
template<class T>
unique_ptr<kdtree<T>>make_kdtree(vector<T>&ps_, const int& l, const int& r, const int& depth = 0) {
	if (l >= r)return nullptr;
	else {
		return make_unique<kdtree<T>>(ps_, l, r, depth);
	}
}

vector<ld>getunit(vector<int>v) {
	vector<ld>unit;
	ld len = 0;
	for (auto&&a : v) {
		len += a*a;
		unit.emplace_back(ld(a));
	}
	len = sqrt(len);
	for (auto&u : unit) {
		u /= len;
	}
	return unit;
}
int gcd(int l, int r) {
	assert(l > 0 && r > 0);
	if (l > r)return gcd(r, l);
	else {
		const  int num = r%l;
		if (num) {
			return gcd(l, num);
		}
		else {
			return l;
		}
	}
}
int gcd(vector<int>nums) {
	if (nums.size() == 1)return nums[0];
	int num = nums[0];

	for (int i = 1; i < nums.size(); ++i) {
		num = gcd(num, nums[i]);
	}
	return num;
}

int main() {
	while (1) {
		answer = Ans{ 1e18,make_pair(-1,-1) };
		int M, N, S, W; cin >> M >> N >> S >> W;
		if (!M&&!N&&!S&&!W)break;
		vector<po>pos;
		vector<vector<int>>memo;
		{
			{
				int nx, ny, nz;
				for (int i = 0; i < M; ++i) {
					cin >> nx >> ny >> nz;
					memo.push_back(vector<int>{nx, ny, nz});
				}
				int g = S;
				for (int i = M; i < M + N; ++i) {
					nx = (g / 7) % 100 + 1;
					ny = (g / 700) % 100 + 1;
					nz = (g / 70000) % 100 + 1;
					memo.push_back(vector<int>{nx, ny, nz});
					if (g % 2 == 0)g = g / 2;
					else g = (g / 2) ^ W;
				}
			}
			{
				vector<vector<int>>newmemo;
				map<vector<int>, int>amap;
				for (int i = 0; i < memo.size(); ++i) {
					int agcd = gcd(memo[i]);
					vector<int>v(3);
					for (int j = 0; j < 3; ++j)v[j] = memo[i][j] / agcd;
					if (amap.find(v) == amap.end() || amap[v] > agcd) {
						amap[v] = agcd;
					}
				}
				for (auto m : amap) {
					auto v = m.first;
					for (int i = 0; i < 3; ++i) {
						v[i] *= m.second;
					}
					newmemo.emplace_back(v);
				}
				memo = newmemo;
			}
			sort(memo.begin(), memo.end(), [](const vector<int>&l, const vector<int>&r) {
				for (int i = 0; i < 3; ++i) {
					if (l[i] == r[i])continue;
					else return l[i] < r[i];
				}
				return false;
			});
			for (int i = 0; i < memo.size(); ++i) {
				po p(i, getunit(memo[i]));
				pos.emplace_back(p);
			}
		}

		auto tree = make_kdtree(pos, 0, pos.size(), 0);
		tree->getmindis();
		auto ansp = answer;
		if (ansp.p.first >ansp.p.second)swap(ansp.p.first, ansp.p.second);
		for (int i = 0; i < 3; ++i) {
			cout << memo[answer.p.first][i] << " ";
		}
		for (int i = 0; i < 3; ++i) {
			cout << memo[answer.p.second][i];
			if (i == 2)cout << endl;
			else cout << " ";
		}
	}
	return 0;
}
accuracy: 1
time_ms: 6530
memory_kb: 26840
final_rank: 15

code_snippet: #include "bits/stdc++.h"
using namespace std;
using ld = long double;
const ld eps = 1e-9;

ld getdis(vector<ld>&l, vector<ld>&r) {
	ld sum = 0;
	for (int i = 0; i < 3; ++i) {
		sum += (l[i] - r[i])*(l[i] - r[i]);
	}
	return sqrt(sum);
}

struct po {
	int index;
	vector<ld> coors;
	po(int _d) :coors(_d) {
		index = -1;
	}
	po(int _index, vector<ld>_coors) :index(_index), coors(_coors) {

	}
	po() {}
};
ld getdis(po&lpo, po&rpo) {
	return getdis(lpo.coors, rpo.coors);
}
template<class T>
class axisSorter {
	int k;
public:
	axisSorter(int _k) : k(_k) {}
	bool operator()(const T &a, const T &b) {
		return a.coors[k] < b.coors[k];
	}
};



struct Ans {
	ld dis;
	pair<int, int>p;

};


bool operator<(const Ans&l, const Ans&r) {
	if (abs(l.dis - r.dis) < eps) {
		assert(l.p.first < l.p.second);
		assert(r.p.first < r.p.second);
		return l.p < r.p;
	}
	else {
		return l.dis < r.dis;
	}
	return true;
}
Ans answer;

template<class T, int Dim = 3>
struct kdtree {
public:
	T midpo;
	vector<T>pos;
	shared_ptr<kdtree<T>> ltree, rtree;
	int depth;
	int axis;
	kdtree(const T &p_) :midpo(p_), ltree(), rtree() {

	}
	~kdtree() {
	}

	kdtree(vector<T>&ps_, const int& l, const int& r, const int depth_ = 0) : ltree(nullptr), rtree(nullptr), depth(depth_), axis(depth%Dim) {
		init(ps_, l, r);
	}
	void getmindis() {
		vector<po>lpos, rpos;
		ld axisvalue = midpo.coors[axis];

		if (ltree != nullptr) {
			for (auto &po : ltree->pos) {
				if (po.coors[axis]>axisvalue - sqrt(answer.dis) - eps * 10) {
					lpos.emplace_back(po);
				}
			}
		}
		if (rtree != nullptr) {
			for (auto &po : rtree->pos) {
				if (po.coors[axis]<axisvalue + sqrt(answer.dis) + eps * 10) {
					rpos.emplace_back(po);
				}
			}
		}

		for (auto& lpo : lpos) {
			for (auto& rpo : rpos) {
				ld dis = getdis(lpo, rpo);
				pair<int, int> p(rpo.index, lpo.index);
				if (p.first > p.second)swap(p.first, p.second);
				Ans nans{ dis,p };
				answer = min(answer, nans);
			}
			{
				ld dis = getdis(lpo, midpo);
				pair<int, int> p(midpo.index, lpo.index);
				if (p.first > p.second)swap(p.first, p.second);
				Ans nans{ dis,p };
				answer = min(answer, nans);
			}
		}
		for (auto& rpo : rpos) {
			ld dis = getdis(midpo, rpo);
			pair<int, int> p(midpo.index, rpo.index);
			if (p.first > p.second)swap(p.first, p.second);
			Ans nans{ dis,p };
			answer = min(answer, nans);
		}


	}
private:
	void init(vector<T>&ps, const int& l, const int& r) {
		if (l >= r) {
			return;
		}
		const int mid = (l + r) / 2;
		nth_element(ps.begin() + l, ps.begin() + mid, ps.begin() + r, axisSorter<T>(axis));
		midpo = ps[mid];

		ltree = make_kdtree(ps, l, mid, depth + 1);
		
		rtree = make_kdtree(ps, mid + 1, r, depth + 1);
		getmindis();
		ltree.reset();
		rtree.reset();
		pos = vector<T>(ps.begin() + l, ps.begin() + r);
	}
};


//[l..r)
template<class T>
unique_ptr<kdtree<T>>make_kdtree(vector<T>&ps_, const int& l, const int& r, const int& depth = 0) {
	if (l >= r)return nullptr;
	else {
		return make_unique<kdtree<T>>(ps_, l, r, depth);
	}
}

vector<ld>getunit(vector<int>v) {
	vector<ld>unit;
	ld len = 0;
	for (auto a : v) {
		len += a*a;
		unit.emplace_back(ld(a));
	}
	len = sqrt(len);
	for (auto&u : unit) {
		u /= len;
	}
	return unit;
}
int gcd(int l, int r) {
	assert(l > 0 && r > 0);
	if (l > r)return gcd(r, l);
	else {
		const  int num = r%l;
		if (num) {
			return gcd(l, num);
		}
		else {
			return l;
		}
	}
}
int gcd(vector<int>nums) {
	if (nums.size() == 1)return nums[0];
	int num = nums[0];

	for (int i = 1; i < nums.size(); ++i) {
		num = gcd(num, nums[i]);
	}
	return num;
}

int main() {
	while (1) {
		answer = Ans{ 1e18,make_pair(-1,-1) };
		int M, N, S, W; cin >> M >> N >> S >> W;
		if (!M&&!N&&!S&&!W)break;
		vector<po>pos;
		vector<vector<int>>memo;
		{
			{
				int nx, ny, nz;
				for (int i = 0; i < M; ++i) {
					cin >> nx >> ny >> nz;
					memo.push_back(vector<int>{nx, ny, nz});
				}
				int g = S;
				for (int i = M; i < M + N; ++i) {
					nx = (g / 7) % 100 + 1;
					ny = (g / 700) % 100 + 1;
					nz = (g / 70000) % 100 + 1;
					memo.push_back(vector<int>{nx, ny, nz});
					if (g % 2 == 0)g = g / 2;
					else g = (g / 2) ^ W;
				}
			}
			sort(memo.begin(), memo.end(), [](const vector<int>&l, const vector<int>&r) {
				for (int i = 0; i < 3; ++i) {
					if (l[i] == r[i])continue;
					else return l[i] < r[i];
				}
				return false;
			});
			{
				vector<vector<int>>newmemo;
				map<vector<int>, int>amap;
				for (int i = 0; i < memo.size(); ++i) {
					int agcd = gcd(memo[i]);
					vector<int>v(3);
					for (int j = 0; j < 3; ++j)v[j] = memo[i][j] / agcd;
					if (amap.find(v) == amap.end() || amap[v] > agcd) {
						amap[v] = agcd;
					}
				}
				for (auto m : amap) {
					auto v = m.first;
					for (int i = 0; i < 3; ++i) {
						v[i] *= m.second;
					}
					newmemo.emplace_back(v);
				}
				memo = newmemo;
			}
			sort(memo.begin(), memo.end(), [](const vector<int>&l, const vector<int>&r) {
				for (int i = 0; i < 3; ++i) {
					if (l[i] == r[i])continue;
					else return l[i] < r[i];
				}
				return false;
			});
			for (int i = 0; i < memo.size(); ++i) {
				po p(i, getunit(memo[i]));
				pos.emplace_back(p);
			}
		}

		auto tree = make_kdtree(pos, 0, pos.size(), 0);
		tree->getmindis();
		auto ansp = answer;
		if (ansp.p.first >ansp.p.second)swap(ansp.p.first, ansp.p.second);
		for (int i = 0; i < 3; ++i) {
			cout << memo[answer.p.first][i] << " ";
		}
		for (int i = 0; i < 3; ++i) {
			cout << memo[answer.p.second][i];
			if (i == 2)cout << endl;
			else cout << " ";
		}
	}
	return 0;
}
accuracy: 1
time_ms: 6300
memory_kb: 26912
final_rank: 14

code_snippet: #include "bits/stdc++.h"
using namespace std;
using ld = long double;
const ld eps = 1e-9;

ld getdis(vector<ld>&l, vector<ld>&r) {
	ld sum = 0;
	for (int i = 0; i < 3; ++i) {
		sum += (l[i] - r[i])*(l[i] - r[i]);
	}
	return sqrt(sum);
}

struct po {
	int index;
	vector<ld> coors;
	po(int _d) :coors(_d) {
		index = -1;
	}
	po(int _index, vector<ld>_coors) :index(_index), coors(_coors) {

	}
	po() {}
};
ld getdis(po&lpo, po&rpo) {
	return getdis(lpo.coors, rpo.coors);
}
template<class T>
class axisSorter {
	int k;
public:
	axisSorter(int _k) : k(_k) {}
	bool operator()(const T &a, const T &b) {
		return a.coors[k] < b.coors[k];
	}
};



struct Ans {
	ld dis;
	pair<int, int>p;

};


bool operator<(const Ans&l, const Ans&r) {
	if (abs(l.dis - r.dis) < eps) {
		assert(l.p.first < l.p.second);
		assert(r.p.first < r.p.second);
		return l.p < r.p;
	}
	else {
		return l.dis < r.dis;
	}
	return true;
}
Ans answer;

template<class T, int Dim = 3>
struct kdtree {
public:
	T midpo;
	vector<T>pos;
	shared_ptr<kdtree<T>> ltree, rtree;
	int depth;
	int axis;
	kdtree(const T &p_) :midpo(p_), ltree(), rtree() {

	}
	~kdtree() {
	}

	kdtree(vector<T>&ps_, const int& l, const int& r, const int depth_ = 0) : ltree(nullptr), rtree(nullptr), depth(depth_), axis(depth%Dim) {
		init(ps_, l, r);
	}
	void getmindis() {
		vector<po>lpos, rpos;
		ld axisvalue = midpo.coors[axis];

		if (ltree != nullptr) {
			for (auto &po : ltree->pos) {
				if (axisvalue>po.coors[axis] - eps * 1000000 && po.coors[axis]>axisvalue - sqrt(answer.dis) - eps * 1000000) {
					lpos.emplace_back(po);
				}
			}
		}
		if (rtree != nullptr) {
			for (auto &po : rtree->pos) {
				if (axisvalue<po.coors[axis] + eps * 1000000 && po.coors[axis]<axisvalue + sqrt(answer.dis) + eps * 1000000) {
					rpos.emplace_back(po);
				}
			}
		}

		for (auto& lpo : lpos) {
			for (auto& rpo : rpos) {
				ld dis = getdis(lpo, rpo);
				pair<int, int> p(rpo.index, lpo.index);
				if (p.first > p.second)swap(p.first, p.second);
				Ans nans{ dis,p };
				answer = min(answer, nans);
			}
			{
				ld dis = getdis(lpo, midpo);
				pair<int, int> p(midpo.index, lpo.index);
				if (p.first > p.second)swap(p.first, p.second);
				Ans nans{ dis,p };
				answer = min(answer, nans);
			}
		}
		for (auto& rpo : rpos) {
			ld dis = getdis(midpo, rpo);
			pair<int, int> p(midpo.index, rpo.index);
			if (p.first > p.second)swap(p.first, p.second);
			Ans nans{ dis,p };
			if (p.first == 1524 && 2763 == p.second) {
				int a = 1; a++;
			}
			//if (p.first == 2763 && 1524 == p.second)assert(false);
			answer = min(answer, nans);
			int b;
			b = 1; b++;
		}


	}
private:
	void init(vector<T>&ps, const int& l, const int& r) {
		if (l >= r) {
			return;
		}
		const int mid = (l + r) / 2;
		nth_element(ps.begin() + l, ps.begin() + mid, ps.begin() + r, axisSorter<T>(axis));
		midpo = ps[mid];

		ltree = make_kdtree(ps, l, mid, depth + 1);
		
		rtree = make_kdtree(ps, mid + 1, r, depth + 1);
		getmindis();
		ltree.reset();
		rtree.reset();
		pos = vector<T>(ps.begin() + l, ps.begin() + r);
	}
};


//[l..r)
template<class T>
unique_ptr<kdtree<T>>make_kdtree(vector<T>&ps_, const int& l, const int& r, const int& depth = 0) {
	if (l >= r)return nullptr;
	else {
		return make_unique<kdtree<T>>(ps_, l, r, depth);
	}
}

vector<ld>getunit(vector<int>v) {
	vector<ld>unit;
	ld len = 0;
	for (auto a : v) {
		len += a*a;
		unit.emplace_back(ld(a));
	}
	len = sqrt(len);
	for (auto&u : unit) {
		u /= len;
	}
	return unit;
}
int gcd(int l, int r) {
	assert(l > 0 && r > 0);
	if (l > r)return gcd(r, l);
	else {
		const  int num = r%l;
		if (num) {
			return gcd(l, num);
		}
		else {
			return l;
		}
	}
}
int gcd(vector<int>nums) {
	if (nums.size() == 1)return nums[0];
	int num = nums[0];

	for (int i = 1; i < nums.size(); ++i) {
		num = gcd(num, nums[i]);
	}
	return num;
}

int main() {
	while (1) {
		answer = Ans{ 1e18,make_pair(-1,-1) };
		int M, N, S, W; cin >> M >> N >> S >> W;
		if (!M&&!N&&!S&&!W)break;
		vector<po>pos;
		vector<vector<int>>memo;
		{
			{
				int nx, ny, nz;
				for (int i = 0; i < M; ++i) {
					cin >> nx >> ny >> nz;
					memo.push_back(vector<int>{nx, ny, nz});
				}
				int g = S;
				for (int i = M; i < M + N; ++i) {
					nx = (g / 7) % 100 + 1;
					ny = (g / 700) % 100 + 1;
					nz = (g / 70000) % 100 + 1;
					memo.push_back(vector<int>{nx, ny, nz});
					if (g % 2 == 0)g = g / 2;
					else g = (g / 2) ^ W;
				}
			}
			sort(memo.begin(), memo.end(), [](const vector<int>&l, const vector<int>&r) {
				for (int i = 0; i < 3; ++i) {
					if (l[i] == r[i])continue;
					else return l[i] < r[i];
				}
				return false;
			});
			{
				vector<vector<int>>newmemo;
				map<vector<int>, int>amap;
				for (int i = 0; i < memo.size(); ++i) {
					int agcd = gcd(memo[i]);
					vector<int>v(3);
					for (int j = 0; j < 3; ++j)v[j] = memo[i][j] / agcd;
					if (amap.find(v) == amap.end() || amap[v] > agcd) {
						amap[v] = agcd;
					}
				}
				for (auto m : amap) {
					auto v = m.first;
					for (int i = 0; i < 3; ++i) {
						v[i] *= m.second;
					}
					newmemo.emplace_back(v);
				}
				memo = newmemo;
			}
			sort(memo.begin(), memo.end(), [](const vector<int>&l, const vector<int>&r) {
				for (int i = 0; i < 3; ++i) {
					if (l[i] == r[i])continue;
					else return l[i] < r[i];
				}
				return false;
			});
			for (int i = 0; i < memo.size(); ++i) {
				po p(i, getunit(memo[i]));
				pos.emplace_back(p);
			}
		}

		auto tree = make_kdtree(pos, 0, pos.size(), 0);
		tree->getmindis();
		auto ansp = answer;
		if (ansp.p.first >ansp.p.second)swap(ansp.p.first, ansp.p.second);
		for (int i = 0; i < 3; ++i) {
			cout << memo[answer.p.first][i] << " ";
		}
		for (int i = 0; i < 3; ++i) {
			cout << memo[answer.p.second][i];
			if (i == 2)cout << endl;
			else cout << " ";
		}
	}
	return 0;
}
//1524,2763
accuracy: 1
time_ms: 6840
memory_kb: 26992
final_rank: 16

code_snippet: #include "bits/stdc++.h"
using namespace std;
using ld = long double;
const ld eps = 1e-9;

ld getdis(vector<ld>&l, vector<ld>&r) {
	ld sum = 0;
	for (int i = 0; i < 3; ++i) {
		sum += (l[i] - r[i])*(l[i] - r[i]);
	}
	return sqrt(sum);
}

struct po {
	int index;
	vector<ld> coors;
	po(int _d) :coors(_d) {
		index = -1;
	}
	po(int _index, vector<ld>_coors) :index(_index), coors(_coors) {

	}
	po() {}
};
ld getdis(po&lpo, po&rpo) {
	return getdis(lpo.coors, rpo.coors);
}
template<class T>
class axisSorter {
	int k;
public:
	axisSorter(int _k) : k(_k) {}
	bool operator()(const T &a, const T &b) {
		return a.coors[k] < b.coors[k];
	}
};



struct Ans {
	ld dis;
	pair<int, int>p;

};


bool operator<(const Ans&l, const Ans&r) {
	if (abs(l.dis - r.dis) < eps) {
		assert(l.p.first < l.p.second);
		assert(r.p.first < r.p.second);
		return l.p < r.p;
	}
	else {
		return l.dis < r.dis;
	}
	return true;
}
Ans answer;

template<class T, int Dim = 3>
struct kdtree {
public:
	T midpo;
	vector<T>pos;
	kdtree<T> *ltree, *rtree;
	int depth;
	int axis;
	kdtree(const T &p_) :midpo(p_), ltree(nullptr), rtree(nullptr) {

	}
	~kdtree() {
		if (ltree != nullptr) {
			delete(ltree);
			ltree = nullptr;
		}

		if (rtree != nullptr) {
			delete(rtree);
			rtree = nullptr;
		}
	}

	kdtree(vector<T>&ps_, const int& l, const int& r, const int depth_ = 0) : ltree(nullptr), rtree(nullptr), depth(depth_), axis(depth%Dim) {
		init(ps_, l, r);
	}
	/*vector<T>query(const T & amin, const T&amax) {
	vector<T>ans;
	bool aok = true;
	for (int i = 0; i < Dim; ++i) {
	if (amin.coors[i] <= midpo.coors[i] && midpo.coors[i] <= amax.coors[i]) {

	}
	else {
	aok = false;
	break;
	}
	}
	if (aok) {
	ans.emplace_back(val);
	}
	axisSorter<T> as(axis);
	if (as(midpo, amax) || midpo.coors[axis] == amax.coors[axis]) {
	if (rtree != nullptr) {
	vector<T>tans(rtree->query(amin, amax));
	ans.insert(ans.end(), tans.begin(), tans.end());
	}
	}
	if (as(amin, midpo) || midpo.coors[axis] == amin.coors[axis]) {
	if (ltree != nullptr) {
	vector<T>tans(ltree->query(amin, amax));
	ans.insert(ans.end(), tans.begin(), tans.end());
	}
	}
	return ans;
	}*/
	void getmindis() {
		/*if (ltree != nullptr) {
		auto p =ltree->getmindis();
		if (ansnum > p.second) {
		ansnum = p.second;
		ansp = p.first;
		}
		}
		if (rtree != nullptr) {
		auto p =  rtree->getmindis();
		if (ansnum > p.second) {
		ansnum = p.second;
		ansp = p.first;
		}
		}*/

		vector<po>lpos, rpos;
		ld axisvalue = midpo.coors[axis];

		if (ltree != nullptr) {
			for (auto &po : ltree->pos) {
				if (axisvalue>po.coors[axis] - eps * 1000000 && po.coors[axis]>axisvalue - sqrt(answer.dis) - eps * 1000000) {
					lpos.emplace_back(po);
				}
			}
		}
		if (rtree != nullptr) {
			for (auto &po : rtree->pos) {
				if (axisvalue<po.coors[axis] + eps * 1000000 && po.coors[axis]<axisvalue + sqrt(answer.dis) + eps * 1000000) {
					rpos.emplace_back(po);
				}
			}
		}

		for (auto& lpo : lpos) {
			for (auto& rpo : rpos) {
				ld dis = getdis(lpo, rpo);
				pair<int, int> p(rpo.index, lpo.index);
				if (p.first > p.second)swap(p.first, p.second);
				Ans nans{ dis,p };
				answer = min(answer, nans);
			}
			{
				ld dis = getdis(lpo, midpo);
				pair<int, int> p(midpo.index, lpo.index);
				if (p.first > p.second)swap(p.first, p.second);
				Ans nans{ dis,p };
				answer = min(answer, nans);
			}
		}
		for (auto& rpo : rpos) {
			ld dis = getdis(midpo, rpo);
			pair<int, int> p(midpo.index, rpo.index);
			if (p.first > p.second)swap(p.first, p.second);
			Ans nans{ dis,p };
			if (p.first == 1524 && 2763 == p.second) {
				int a = 1; a++;
			}
			//if (p.first == 2763 && 1524 == p.second)assert(false);
			answer = min(answer, nans);
			int b;
			b = 1; b++;
		}


	}
private:
	void init(vector<T>&ps, const int& l, const int& r) {
		if (l >= r) {
			return;
		}
		const int mid = (l + r) / 2;
		nth_element(ps.begin() + l, ps.begin() + mid, ps.begin() + r, axisSorter<T>(axis));
		midpo = ps[mid];

		ltree = make_kdtree(ps, l, mid, depth + 1);
		
		rtree = make_kdtree(ps, mid + 1, r, depth + 1);
		getmindis();
		if (ltree) {
			delete(ltree);
			ltree = nullptr;
		}
		if (rtree) {
			delete(rtree);
			rtree = nullptr;
		}
		pos = vector<T>(ps.begin() + l, ps.begin() + r);
	}
};


//[l..r)
template<class T>
kdtree<T> *make_kdtree(vector<T>&ps_, const int& l, const int& r, const int& depth = 0) {
	if (l >= r)return nullptr;
	else {
		return new kdtree<T>(ps_, l, r, depth);
	}
}

vector<ld>getunit(vector<int>v) {
	vector<ld>unit;
	ld len = 0;
	for (auto a : v) {
		len += a*a;
		unit.emplace_back(ld(a));
	}
	len = sqrt(len);
	for (auto&u : unit) {
		u /= len;
	}
	return unit;
}
int gcd(int l, int r) {
	assert(l > 0 && r > 0);
	if (l > r)return gcd(r, l);
	else {
		const  int num = r%l;
		if (num) {
			return gcd(l, num);
		}
		else {
			return l;
		}
	}
}
int gcd(vector<int>nums) {
	if (nums.size() == 1)return nums[0];
	int num = nums[0];

	for (int i = 1; i < nums.size(); ++i) {
		num = gcd(num, nums[i]);
	}
	return num;
}

int main() {
	while (1) {
		answer = Ans{ 1e18,make_pair(-1,-1) };
		int M, N, S, W; cin >> M >> N >> S >> W;
		if (!M&&!N&&!S&&!W)break;
		vector<po>pos;
		vector<vector<int>>memo;
		{
			{
				int nx, ny, nz;
				for (int i = 0; i < M; ++i) {
					cin >> nx >> ny >> nz;
					memo.push_back(vector<int>{nx, ny, nz});
				}
				int g = S;
				for (int i = M; i < M + N; ++i) {
					nx = (g / 7) % 100 + 1;
					ny = (g / 700) % 100 + 1;
					nz = (g / 70000) % 100 + 1;
					memo.push_back(vector<int>{nx, ny, nz});
					if (g % 2 == 0)g = g / 2;
					else g = (g / 2) ^ W;
				}
			}
			sort(memo.begin(), memo.end(), [](const vector<int>&l, const vector<int>&r) {
				for (int i = 0; i < 3; ++i) {
					if (l[i] == r[i])continue;
					else return l[i] < r[i];
				}
				return false;
			});
			{
				vector<vector<int>>newmemo;
				map<vector<int>, int>amap;
				for (int i = 0; i < memo.size(); ++i) {
					int agcd = gcd(memo[i]);
					vector<int>v(3);
					for (int j = 0; j < 3; ++j)v[j] = memo[i][j] / agcd;
					if (amap.find(v) == amap.end() || amap[v] > agcd) {
						amap[v] = agcd;
					}
				}
				for (auto m : amap) {
					auto v = m.first;
					for (int i = 0; i < 3; ++i) {
						v[i] *= m.second;
					}
					newmemo.emplace_back(v);
				}
				memo = newmemo;
			}
			sort(memo.begin(), memo.end(), [](const vector<int>&l, const vector<int>&r) {
				for (int i = 0; i < 3; ++i) {
					if (l[i] == r[i])continue;
					else return l[i] < r[i];
				}
				return false;
			});
			for (int i = 0; i < memo.size(); ++i) {
				po p(i, getunit(memo[i]));
				pos.emplace_back(p);
			}
		}

		auto tree = make_kdtree(pos, 0, pos.size(), 0);
		tree->getmindis();
		auto ansp = answer;
		if (ansp.p.first >ansp.p.second)swap(ansp.p.first, ansp.p.second);
		for (int i = 0; i < 3; ++i) {
			cout << memo[answer.p.first][i] << " ";
		}
		for (int i = 0; i < 3; ++i) {
			cout << memo[answer.p.second][i];
			if (i == 2)cout << endl;
			else cout << " ";
		}
		delete(tree);
	}
	return 0;
}
//1524,2763
accuracy: 1
time_ms: 6990
memory_kb: 26888
final_rank: 17

code_snippet: #include "bits/stdc++.h"
using namespace std;
using ld = long double;
const ld eps = 1e-9;

ld getdis(vector<ld>&l, vector<ld>&r) {
	ld sum = 0;
	for (int i = 0; i < 3; ++i) {
		sum += (l[i] - r[i])*(l[i] - r[i]);
	}
	return sqrt(sum);
}

struct po {
	int index;
	vector<ld> coors;
	po(int _d) :coors(_d) {
		index = -1;
	}
	po(int _index, vector<ld>_coors) :index(_index), coors(_coors) {

	}
	po() {}
};
ld getdis(po&lpo, po&rpo) {
	return getdis(lpo.coors, rpo.coors);
}
template<class T>
class axisSorter {
	int k;
public:
	axisSorter(int _k) : k(_k) {}
	bool operator()(const T &a, const T &b) {
		return a.coors[k] < b.coors[k];
	}
};



struct Ans {
	ld dis;
	pair<int, int>p;

};


bool operator<(const Ans&l, const Ans&r) {
	if (abs(l.dis - r.dis) < eps) {
		assert(l.p.first < l.p.second);
		assert(r.p.first < r.p.second);
		return l.p < r.p;
	}
	else {
		return l.dis < r.dis;
	}
	return true;
}
Ans answer;

template<class T, int Dim = 3>
struct kdtree {
public:
	T midpo;
	vector<T>pos;
	kdtree<T> *ltree, *rtree;
	int depth;
	int axis;
	kdtree(const T &p_) :midpo(p_), ltree(nullptr), rtree(nullptr) {

	}
	~kdtree() {
		if (ltree != nullptr) {
			delete(ltree);
			ltree = nullptr;
		}

		if (rtree != nullptr) {
			delete(rtree);
			rtree = nullptr;
		}
	}

	kdtree(vector<T>&ps_, const int& l, const int& r, const int depth_ = 0) : ltree(nullptr), rtree(nullptr), depth(depth_), axis(depth%Dim) {
		init(ps_, l, r);
	}
	/*vector<T>query(const T & amin, const T&amax) {
	vector<T>ans;
	bool aok = true;
	for (int i = 0; i < Dim; ++i) {
	if (amin.coors[i] <= midpo.coors[i] && midpo.coors[i] <= amax.coors[i]) {

	}
	else {
	aok = false;
	break;
	}
	}
	if (aok) {
	ans.emplace_back(val);
	}
	axisSorter<T> as(axis);
	if (as(midpo, amax) || midpo.coors[axis] == amax.coors[axis]) {
	if (rtree != nullptr) {
	vector<T>tans(rtree->query(amin, amax));
	ans.insert(ans.end(), tans.begin(), tans.end());
	}
	}
	if (as(amin, midpo) || midpo.coors[axis] == amin.coors[axis]) {
	if (ltree != nullptr) {
	vector<T>tans(ltree->query(amin, amax));
	ans.insert(ans.end(), tans.begin(), tans.end());
	}
	}
	return ans;
	}*/
	void getmindis() {
		/*if (ltree != nullptr) {
		auto p =ltree->getmindis();
		if (ansnum > p.second) {
		ansnum = p.second;
		ansp = p.first;
		}
		}
		if (rtree != nullptr) {
		auto p =  rtree->getmindis();
		if (ansnum > p.second) {
		ansnum = p.second;
		ansp = p.first;
		}
		}*/

		vector<po>lpos, rpos;
		ld axisvalue = midpo.coors[axis];

		if (ltree != nullptr) {
			for (auto &po : ltree->pos) {
				if (axisvalue>po.coors[axis] - eps * 1000000 && po.coors[axis]>axisvalue - sqrt(answer.dis) - eps * 1000000) {
					lpos.emplace_back(po);
				}
			}
		}
		if (rtree != nullptr) {
			for (auto &po : rtree->pos) {
				if (axisvalue<po.coors[axis] + eps * 1000000 && po.coors[axis]<axisvalue + sqrt(answer.dis) + eps * 1000000) {
					rpos.emplace_back(po);
				}
			}
		}

		for (auto& lpo : lpos) {
			for (auto& rpo : rpos) {
				ld dis = getdis(lpo, rpo);
				pair<int, int> p(rpo.index, lpo.index);
				if (p.first > p.second)swap(p.first, p.second);
				Ans nans{ dis,p };
				answer = min(answer, nans);
			}
			{
				ld dis = getdis(lpo, midpo);
				pair<int, int> p(midpo.index, lpo.index);
				if (p.first > p.second)swap(p.first, p.second);
				Ans nans{ dis,p };
				answer = min(answer, nans);
			}
		}
		for (auto& rpo : rpos) {
			ld dis = getdis(midpo, rpo);
			pair<int, int> p(midpo.index, rpo.index);
			if (p.first > p.second)swap(p.first, p.second);
			Ans nans{ dis,p };
			if (p.first == 1524 && 2763 == p.second) {
				int a = 1; a++;
			}
			//if (p.first == 2763 && 1524 == p.second)assert(false);
			answer = min(answer, nans);
			int b;
			b = 1; b++;
		}


	}
private:
	void init(vector<T>&ps, const int& l, const int& r) {
		if (l >= r) {
			return;
		}
		sort(ps.begin() + l, ps.begin() + r, axisSorter<T>(axis));
		const int mid = (l + r) / 2;
		midpo = ps[mid];

		ltree = make_kdtree(ps, l, mid, depth + 1);
		
		rtree = make_kdtree(ps, mid + 1, r, depth + 1);
		getmindis();
		if (ltree) {
			delete(ltree);
			ltree = nullptr;
		}
		if (rtree) {
			delete(rtree);
			rtree = nullptr;
		}
		pos = vector<T>(ps.begin() + l, ps.begin() + r);
	}
};


//[l..r)
template<class T>
kdtree<T> *make_kdtree(vector<T>&ps_, const int& l, const int& r, const int& depth = 0) {
	if (l >= r)return nullptr;
	else {
		return new kdtree<T>(ps_, l, r, depth);
	}
}

vector<ld>getunit(vector<int>v) {
	vector<ld>unit;
	ld len = 0;
	for (auto a : v) {
		len += a*a;
		unit.emplace_back(ld(a));
	}
	len = sqrt(len);
	for (auto&u : unit) {
		u /= len;
	}
	return unit;
}
int gcd(int l, int r) {
	assert(l > 0 && r > 0);
	if (l > r)return gcd(r, l);
	else {
		const  int num = r%l;
		if (num) {
			return gcd(l, num);
		}
		else {
			return l;
		}
	}
}
int gcd(vector<int>nums) {
	if (nums.size() == 1)return nums[0];
	int num = nums[0];

	for (int i = 1; i < nums.size(); ++i) {
		num = gcd(num, nums[i]);
	}
	return num;
}

int main() {
	while (1) {
		answer = Ans{ 1e18,make_pair(-1,-1) };
		int M, N, S, W; cin >> M >> N >> S >> W;
		if (!M&&!N&&!S&&!W)break;
		vector<po>pos;
		vector<vector<int>>memo;
		{
			{
				int nx, ny, nz;
				for (int i = 0; i < M; ++i) {
					cin >> nx >> ny >> nz;
					memo.push_back(vector<int>{nx, ny, nz});
				}
				int g = S;
				for (int i = M; i < M + N; ++i) {
					nx = (g / 7) % 100 + 1;
					ny = (g / 700) % 100 + 1;
					nz = (g / 70000) % 100 + 1;
					memo.push_back(vector<int>{nx, ny, nz});
					if (g % 2 == 0)g = g / 2;
					else g = (g / 2) ^ W;
				}
			}
			sort(memo.begin(), memo.end(), [](const vector<int>&l, const vector<int>&r) {
				for (int i = 0; i < 3; ++i) {
					if (l[i] == r[i])continue;
					else return l[i] < r[i];
				}
				return false;
			});
			{
				vector<vector<int>>newmemo;
				map<vector<int>, int>amap;
				for (int i = 0; i < memo.size(); ++i) {
					int agcd = gcd(memo[i]);
					vector<int>v(3);
					for (int j = 0; j < 3; ++j)v[j] = memo[i][j] / agcd;
					if (amap.find(v) == amap.end() || amap[v] > agcd) {
						amap[v] = agcd;
					}
				}
				for (auto m : amap) {
					auto v = m.first;
					for (int i = 0; i < 3; ++i) {
						v[i] *= m.second;
					}
					newmemo.emplace_back(v);
				}
				memo = newmemo;
			}
			sort(memo.begin(), memo.end(), [](const vector<int>&l, const vector<int>&r) {
				for (int i = 0; i < 3; ++i) {
					if (l[i] == r[i])continue;
					else return l[i] < r[i];
				}
				return false;
			});
			for (int i = 0; i < memo.size(); ++i) {
				po p(i, getunit(memo[i]));
				pos.emplace_back(p);
			}
		}

		auto tree = make_kdtree(pos, 0, pos.size(), 0);
		tree->getmindis();
		auto ansp = answer;
		if (ansp.p.first >ansp.p.second)swap(ansp.p.first, ansp.p.second);
		for (int i = 0; i < 3; ++i) {
			cout << memo[answer.p.first][i] << " ";
		}
		for (int i = 0; i < 3; ++i) {
			cout << memo[answer.p.second][i];
			if (i == 2)cout << endl;
			else cout << " ";
		}
		delete(tree);
	}
	return 0;
}
//1524,2763
accuracy: 1
time_ms: 7820
memory_kb: 26876
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;

namespace ClosestPair{
	// DIM=3????£????????¬????????????????????????´?????????getNearPoints()?????´
	const double EPS = 1e-9;
	const int DIM = 3;
	typedef array<double,DIM> P;

	double dist(const P &p1,const P &p2){
		double ans = 0;
		for(int i = 0 ; i < DIM ; i++)
			ans += (p1[i]-p2[i])*(p1[i]-p2[i]);
		return sqrt(ans);
	}
	typedef array<int,DIM> Block;
	typedef unordered_map<unsigned long long,vector<int>> Bucket;
	Block getBlock(const P &p,double w){
		Block res;
		for(int i = 0 ; i < DIM ; i++) res[i] = p[i] / w;
		return res;
	}
	unsigned long long toHash(const Block &bl){
		unsigned long long h = 0;
		for(int i = 0 ; i < DIM ; i++){
			h = h * 100000007 + bl[i];
		}
		return h;
	}
	vector<int> getNearPoints(const Bucket &b,double w,const P &p){
		vector<int> res;
		auto key = getBlock(p,w);
		for(int x0 = -1 ; x0 <= 1 ; x0++)
			for(int x1 = -1 ; x1 <= 1 ; x1++){
				for(int x2 = -1 ; x2 <= 1 ; x2++){
					auto it = b.find(toHash(Block{key[0]+x0,key[1]+x1,key[2]+x2}));
					if( it != b.end() ){
						for( int id : it->second ) res.push_back(id);
					}
				}
			}
		return res;
	}
	//???w???n?¬?????????±????????????????????????????????¨????????°??¨??????????????????????±????????????¨?????§?????????
	Bucket makeBucket(const vector<P> &ps,double w){
		Bucket b;
		for(int i = 0 ; i < ps.size() ; i++)
			b[toHash(getBlock(ps[i],w))].push_back(i);
		return b;
	}
	// ????????????????????¢????????????????????±???????¬??§??????? map????????¨?????????????????§???????¨???????O(n log n)
	// ?????±??????????????????????§???????????????????????¢????????£?????????????????????????????????§??????????????§???????????????2w??????????????????????????????w???????????????????\??????????
	double closetPairDistance(vector<P> ps){
		assert(ps.size()>=2);
		random_shuffle(ps.begin(),ps.end());
		double w = dist(ps[0],ps[1]);
		vector<P> build = {ps[0],ps[1]};
		auto b = makeBucket(build,w);
		int a = 0;
		for(int i = 2 ; i < ps.size() ; i++){
			double next_w = w;
			for( int j : getNearPoints(b,w,ps[i]) )
				next_w = min(next_w,dist(ps[i],ps[j]));
			build.push_back(ps[i]);
			if( w - EPS > next_w ){
				w = next_w;
				b = makeBucket(build,w);
				a++;
			}else{
				b[toHash(getBlock(ps[i],w))].push_back(i);
			}
		}
		return w;
	}
};
using namespace ClosestPair;


struct Pt{
	double x,y,z;
};
bool operator < (const Pt &a,const Pt &b){
	if( fabs(a.x-b.x) > EPS ) return a.x < b.x;
	if( fabs(a.y-b.y) > EPS ) return a.y < b.y;
	if( fabs(a.z-b.z) > EPS ) return a.z < b.z;
	return false;
}

double X[150000];
double Y[150000];
double Z[150000];
int main(){
    int m,n,S,W;
    int tst = 1;
    while( cin >> m >> n >> S >> W && m+n ){
        map<Pt,vector<P>> dic;
        for(int i = 0 ; i < m ; i++){
            scanf("%lf%lf%lf",X+i,Y+i,Z+i);
        }
        int g = S;
        for(int i=m; i<m+n; i++) {
          X[i] = (g/7)    %100 + 1;
          Y[i] = (g/700)  %100 + 1;
          Z[i] = (g/70000)%100 + 1;
          if( g%2 == 0 ) { g = (g/2); }
          else           { g = (g/2) ^ W; }
        }
        for(int i = 0 ; i < m+n ; i++){
            double x = X[i];
            double y = Y[i];
            double z = Z[i];
            P p = {x,y,z};
            double d = dist(P{0,0,0},p);
            Pt e;
            e.x = x / d;
            e.y = y / d;
            e.z = z / d;
            dic[e].push_back(p);
        }
        vector<P> ps;
        vector<P> cand;
        for( auto &p : dic ){
            ps.push_back(P{p.first.x,p.first.y,p.first.z});
             
            cand.push_back(*min_element(p.second.begin(),p.second.end()));
        }
     
        double w = closetPairDistance(ps);
        auto b = makeBucket(ps,w);
        pair<P,P> best = {P{1e9,1e9,1e9},P{1e9,1e9,1e9}};
        for(int i = 0 ; i < ps.size() ; i++){
            for( auto j : getNearPoints(b,w,ps[i]) ){
                if( i != j ){
                    if( fabs(dist(ps[i],ps[j])-w) < EPS ){
                        best = min(best,pair<P,P>{cand[i],cand[j]});
                    }
                }
            }
        }
        cout << (int)best.first[0] << " " << (int)best.first[1] << " " << (int)best.first[2] << " ";
        cout << (int)best.second[0] << " " << (int)best.second[1] << " " << (int)best.second[2] << "\n";
    }
     
 
}
accuracy: 1
time_ms: 4330
memory_kb: 41448
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;

namespace ClosestPair{
	// DIM=3????£????????¬????????????????????????´?????????getNearPoints()makeBucket()?????´
	const double EPS = 1e-9;
	const int DIM = 3;
	typedef array<double,DIM> P;

	double dist(const P &p1,const P &p2){
		double ans = 0;
		for(int i = 0 ; i < DIM ; i++)
			ans += (p1[i]-p2[i])*(p1[i]-p2[i]);
		return sqrt(ans);
	}
	typedef array<int,DIM> Block;
	typedef map<Block,vector<int>> Bucket;
	Block getBlock(const P &p,double w){
		Block res;
		for(int i = 0 ; i < DIM ; i++) res[i] = p[i] / w;
		return res;
	}
	vector<int> getNearPoints(const Bucket &b,double w,const P &p){
		vector<int> res;
		auto key = getBlock(p,w);
		for(int x0 = -1 ; x0 <= 1 ; x0++)
			for(int x1 = -1 ; x1 <= 1 ; x1++)
				for(int x2 = -1 ; x2 <= 1 ; x2++){
					auto it = b.find(Block{key[0]+x0,key[1]+x1,key[2]+x2});
					if( it != b.end() ){
						for( int id : it->second ) res.push_back(id);
					}
				}
		return res;
	}
	//???w???n?¬?????????±????????????????????????????????¨????????°??¨??????????????????????±????????????¨?????§?????????
	Bucket makeBucket(const vector<P> &ps,double w){
		Bucket b;
		for(int i = 0 ; i < ps.size() ; i++)
			b[getBlock(ps[i],w)].push_back(i);
		return b;
	}
	// ????????????????????¢????????????????????±???????¬??§??????? map????????¨?????????????????§???????¨???????O(n log n)
	// ?????±??????????????????????§???????????????????????¢????????£?????????????????????????????????§??????????????§???????????????2w??????????????????????????????w???????????????????\??????????
	double closetPairDistance(vector<P> ps){
		double w = 1e9;
		for( auto &p : ps ){
			tie(p[0],p[1]) = make_pair(p[0]*cos(0)-p[1]*sin(0),p[0]*sin(0)+p[1]*cos(0));
		}
		sort(ps.begin(),ps.end());
		for(int i = 0 ; i < ps.size() ; i++){
			for(int j = i-1 ; j >= 0 ; j--){
				if( ps[i][0]-ps[j][0] >= w ) break;
				w = min(w,dist(ps[i],ps[j]));
			}
		}
		return w;
	}
};

using namespace ClosestPair;


struct Pt{
	double x,y,z;
};
bool operator < (const Pt &a,const Pt &b){
	if( fabs(a.x-b.x) > EPS ) return a.x < b.x;
	if( fabs(a.y-b.y) > EPS ) return a.y < b.y;
	if( fabs(a.z-b.z) > EPS ) return a.z < b.z;
	return false;
}

double X[150000];
double Y[150000];
double Z[150000];

int main(){
	int m,n,S,W;
	int tst = 1;
	while( cin >> m >> n >> S >> W && m+n ){
		map<Pt,vector<P>> dic;
		for(int i = 0 ; i < m ; i++){
			scanf("%lf%lf%lf",X+i,Y+i,Z+i);
		}
		int g = S;
		for(int i=m; i<m+n; i++) {
		  X[i] = (g/7)    %100 + 1;
		  Y[i] = (g/700)  %100 + 1;
		  Z[i] = (g/70000)%100 + 1;
		  if( g%2 == 0 ) { g = (g/2); }
		  else           { g = (g/2) ^ W; }
		}
		for(int i = 0 ; i < m+n ; i++){
			double x = X[i];
			double y = Y[i];
			double z = Z[i];
			P p = {x,y,z};
			double d = dist(P{0,0,0},p);
			Pt e;
			e.x = x / d;
			e.y = y / d;
			e.z = z / d;
			dic[e].push_back(p);
		}
		vector<P> ps;
		vector<P> cand;
		for( auto &p : dic ){
			ps.push_back(P{p.first.x,p.first.y,p.first.z});
			
			cand.push_back(*min_element(p.second.begin(),p.second.end()));
		}
	
		double w = closetPairDistance(ps);
		auto b = makeBucket(ps,2*w);
		pair<P,P> best = {P{1e9,1e9,1e9},P{1e9,1e9,1e9}};
		for(int i = 0 ; i < ps.size() ; i++){
			for( auto j : getNearPoints(b,2*w,ps[i]) ){
				if( i != j ){
					if( fabs(dist(ps[i],ps[j])-w) < EPS ){
						best = min(best,pair<P,P>{cand[i],cand[j]});
					}
				}
			}
		}
		cout << (int)best.first[0] << " " << (int)best.first[1] << " " << (int)best.first[2] << " ";
		cout << (int)best.second[0] << " " << (int)best.second[1] << " " << (int)best.second[2] << "\n";
	}
	

}
accuracy: 1
time_ms: 3580
memory_kb: 31536
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;

namespace ClosestPair{
	// DIM=3????£????????¬????????????????????????´?????????getNearPoints()makeBucket()?????´
	const double EPS = 1e-9;
	const int DIM = 3;
	typedef array<double,DIM> P;

	double dist(const P &p1,const P &p2){
		double ans = 0;
		for(int i = 0 ; i < DIM ; i++)
			ans += (p1[i]-p2[i])*(p1[i]-p2[i]);
		return sqrt(ans);
	}
	typedef array<int,DIM> Block;
	typedef map<Block,vector<int>> Bucket;
	Block getBlock(const P &p,double w){
		Block res;
		for(int i = 0 ; i < DIM ; i++) res[i] = p[i] / w;
		return res;
	}
	vector<int> getNearPoints(const Bucket &b,double w,const P &p){
		vector<int> res;
		auto key = getBlock(p,w);
		for(int x0 = -1 ; x0 <= 1 ; x0++)
			for(int x1 = -1 ; x1 <= 1 ; x1++)
				for(int x2 = -1 ; x2 <= 1 ; x2++){
					auto it = b.find(Block{key[0]+x0,key[1]+x1,key[2]+x2});
					if( it != b.end() ){
						for( int id : it->second ) res.push_back(id);
					}
				}
		return res;
	}
	//???w???n?¬?????????±????????????????????????????????¨????????°??¨??????????????????????±????????????¨?????§?????????
	Bucket makeBucket(const vector<P> &ps,double w){
		Bucket b;
		for(int i = 0 ; i < ps.size() ; i++)
			b[getBlock(ps[i],w)].push_back(i);
		return b;
	}
	// ????????????????????¢????????????????????±???????¬??§??????? map????????¨?????????????????§???????¨???????O(n log n)
	// ?????±??????????????????????§???????????????????????¢????????£?????????????????????????????????§??????????????§???????????????2w??????????????????????????????w???????????????????\??????????
	double closetPairDistance(vector<P> ps){
		double w = 1e9;
		for( auto &p : ps ){
			tie(p[0],p[1]) = make_pair(p[0]*cos(2)-p[1]*sin(2),p[0]*sin(2)+p[1]*cos(2));
		}
		sort(ps.begin(),ps.end());
		for(int i = 0 ; i < ps.size() ; i++){
			for(int j = i-1 ; j >= 0 ; j--){
				if( ps[i][0]-ps[j][0] >= w ) break;
				w = min(w,dist(ps[i],ps[j]));
			}
		}
		return w;
	}
};

using namespace ClosestPair;


struct Pt{
	double x,y,z;
};
bool operator < (const Pt &a,const Pt &b){
	if( fabs(a.x-b.x) > EPS ) return a.x < b.x;
	if( fabs(a.y-b.y) > EPS ) return a.y < b.y;
	if( fabs(a.z-b.z) > EPS ) return a.z < b.z;
	return false;
}

double X[150000];
double Y[150000];
double Z[150000];

int main(){
	int m,n,S,W;
	int tst = 1;
	while( cin >> m >> n >> S >> W && m+n ){
		map<Pt,vector<P>> dic;
		for(int i = 0 ; i < m ; i++){
			scanf("%lf%lf%lf",X+i,Y+i,Z+i);
		}
		int g = S;
		for(int i=m; i<m+n; i++) {
		  X[i] = (g/7)    %100 + 1;
		  Y[i] = (g/700)  %100 + 1;
		  Z[i] = (g/70000)%100 + 1;
		  if( g%2 == 0 ) { g = (g/2); }
		  else           { g = (g/2) ^ W; }
		}
		for(int i = 0 ; i < m+n ; i++){
			double x = X[i];
			double y = Y[i];
			double z = Z[i];
			P p = {x,y,z};
			double d = dist(P{0,0,0},p);
			Pt e;
			e.x = x / d;
			e.y = y / d;
			e.z = z / d;
			dic[e].push_back(p);
		}
		vector<P> ps;
		vector<P> cand;
		for( auto &p : dic ){
			ps.push_back(P{p.first.x,p.first.y,p.first.z});
			
			cand.push_back(*min_element(p.second.begin(),p.second.end()));
		}
	
		double w = closetPairDistance(ps);
		auto b = makeBucket(ps,2*w);
		pair<P,P> best = {P{1e9,1e9,1e9},P{1e9,1e9,1e9}};
		for(int i = 0 ; i < ps.size() ; i++){
			for( auto j : getNearPoints(b,2*w,ps[i]) ){
				if( i != j ){
					if( fabs(dist(ps[i],ps[j])-w) < EPS ){
						best = min(best,pair<P,P>{cand[i],cand[j]});
					}
				}
			}
		}
		cout << (int)best.first[0] << " " << (int)best.first[1] << " " << (int)best.first[2] << " ";
		cout << (int)best.second[0] << " " << (int)best.second[1] << " " << (int)best.second[2] << "\n";
	}
	

}
accuracy: 1
time_ms: 3670
memory_kb: 31612
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;

namespace ClosestPair{
	// DIM=3????£????????¬????????????????????????´?????????getNearPoints()makeBucket()?????´
	const double EPS = 1e-9;
	const int DIM = 3;
	typedef array<double,DIM> P;

	double dist(const P &p1,const P &p2){
		double ans = 0;
		for(int i = 0 ; i < DIM ; i++)
			ans += (p1[i]-p2[i])*(p1[i]-p2[i]);
		return sqrt(ans);
	}
	typedef array<int,DIM> Block;
	typedef map<Block,vector<int>> Bucket;
	Block getBlock(const P &p,double w){
		Block res;
		for(int i = 0 ; i < DIM ; i++) res[i] = p[i] / w;
		return res;
	}
	vector<int> getNearPoints(const Bucket &b,double w,const P &p){
		vector<int> res;
		auto key = getBlock(p,w);
		for(int x0 = -1 ; x0 <= 1 ; x0++)
			for(int x1 = -1 ; x1 <= 1 ; x1++)
				for(int x2 = -1 ; x2 <= 1 ; x2++){
					auto it = b.find(Block{key[0]+x0,key[1]+x1,key[2]+x2});
					if( it != b.end() ){
						for( int id : it->second ) res.push_back(id);
					}
				}
		return res;
	}
	//???w???n?¬?????????±????????????????????????????????¨????????°??¨??????????????????????±????????????¨?????§?????????
	Bucket makeBucket(const vector<P> &ps,double w){
		Bucket b;
		for(int i = 0 ; i < ps.size() ; i++)
			b[getBlock(ps[i],w)].push_back(i);
		return b;
	}
	// ????????????????????¢????????????????????±???????¬??§??????? map????????¨?????????????????§???????¨???????O(n log n)
	// ?????±??????????????????????§???????????????????????¢????????£?????????????????????????????????§??????????????§???????????????2w??????????????????????????????w???????????????????\??????????
	double closetPairDistance(vector<P> ps){
		assert(ps.size()>=2);
		random_shuffle(ps.begin(),ps.end());
		double w = dist(ps[0],ps[1]);
		vector<P> build = {ps[0],ps[1]};
		auto b = makeBucket(build,2*w);
		for(int i = 2 ; i < ps.size() ; i++){
			double next_w = w;
			for( int j : getNearPoints(b,2*w,ps[i]) )
				next_w = min(next_w,dist(ps[i],ps[j]));
			build.push_back(ps[i]);
			if( w - EPS > next_w ){
				w = next_w;
				b = makeBucket(build,2*w);
			}else{
				b[getBlock(ps[i],2*w)].push_back(i);
			}
		}
		return w;
	}
};

using namespace ClosestPair;


struct Pt{
	double x,y,z;
};
bool operator < (const Pt &a,const Pt &b){
	if( fabs(a.x-b.x) > EPS ) return a.x < b.x;
	if( fabs(a.y-b.y) > EPS ) return a.y < b.y;
	if( fabs(a.z-b.z) > EPS ) return a.z < b.z;
	return false;
}

double X[150000];
double Y[150000];
double Z[150000];

int main(){
	int m,n,S,W;
	int tst = 1;
	while( cin >> m >> n >> S >> W && m+n ){
		map<Pt,vector<P>> dic;
		for(int i = 0 ; i < m ; i++){
			scanf("%lf%lf%lf",X+i,Y+i,Z+i);
		}
		int g = S;
		for(int i=m; i<m+n; i++) {
		  X[i] = (g/7)    %100 + 1;
		  Y[i] = (g/700)  %100 + 1;
		  Z[i] = (g/70000)%100 + 1;
		  if( g%2 == 0 ) { g = (g/2); }
		  else           { g = (g/2) ^ W; }
		}
		for(int i = 0 ; i < m+n ; i++){
			double x = X[i];
			double y = Y[i];
			double z = Z[i];
			P p = {x,y,z};
			double d = dist(P{0,0,0},p);
			Pt e;
			e.x = x / d;
			e.y = y / d;
			e.z = z / d;
			dic[e].push_back(p);
		}
		vector<P> ps;
		vector<P> cand;
		for( auto &p : dic ){
			ps.push_back(P{p.first.x,p.first.y,p.first.z});
			
			cand.push_back(*min_element(p.second.begin(),p.second.end()));
		}
	
		double w = closetPairDistance(ps);
		auto b = makeBucket(ps,2*w);
		pair<P,P> best = {P{1e9,1e9,1e9},P{1e9,1e9,1e9}};
		for(int i = 0 ; i < ps.size() ; i++){
			for( auto j : getNearPoints(b,2*w,ps[i]) ){
				if( i != j ){
					if( fabs(dist(ps[i],ps[j])-w) < EPS ){
						best = min(best,pair<P,P>{cand[i],cand[j]});
					}
				}
			}
		}
		cout << (int)best.first[0] << " " << (int)best.first[1] << " " << (int)best.first[2] << " ";
		cout << (int)best.second[0] << " " << (int)best.second[1] << " " << (int)best.second[2] << "\n";
		
	}
	

}
accuracy: 1
time_ms: 7430
memory_kb: 44408
final_rank: 20