#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int n = 5000;
const int m = 5;
const int Dmax = n + 100;
const int nbits = 3 * log2(n);
int D, r, itor[Dmax] = {}, rtoi[Dmax];
long long d[n];
inline long long cube(int i)
{
return (long long)i * i * i;
}
inline int atob(int a)
{
int rb;
if ((rb = itor[a] - r) < 0) rb += D;
return rtoi[rb];
}
inline void PrintSolution(long long *p)
{
int a, b;
bool first = true;
cout << *p << ": ";
for (a = 2; a <= n; a++) {
if (b = atob(a), b == 0 || b >= a) continue;
if (*p != cube(a) - cube(b)) continue;
cout << (first ? first = false, "(" : ", (") << a << ", " << b << ")";
}
cout << endl;
}
void FindDuplicates(long long *p, long long *q, int depth)
{
if (q - p < m) return;
if (depth < 0) return PrintSolution(p);
long long mask = 1LL << depth;
long long *P = partition(p, q, [&](long long x) {return !(x & mask);});
FindDuplicates(p, P, depth - 1);
FindDuplicates(P, q, depth - 1);
}
int main(void)
{
int a, b, i;
for (D = n + 1; D <= Dmax; D++) {
fill(rtoi, rtoi + D, 0);
for (i = 1; i <= n; i++) {
r = cube(i) % D;
if (rtoi[r]) break; else rtoi[r] = i;
}
if (i > n) break;
}
if (D > Dmax) return cout << "D not found." << endl, 1;
for (r = 0; r < D; r++) itor[rtoi[r]] = r;
for (r = 1; r < D; r++) {
for (i = 0, a = 2; a <= n; a++) {
if (b = atob(a), b == 0 || b >= a) continue;
d[i++] = cube(a) - cube(b);
}
FindDuplicates(d, d + i, nbits);
}
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8YWxnb3JpdGhtPgojaW5jbHVkZSA8Y21hdGg+Cgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKY29uc3QgaW50IG4gPSA1MDAwOwpjb25zdCBpbnQgbSA9IDU7CmNvbnN0IGludCBEbWF4ID0gbiArIDEwMDsKY29uc3QgaW50IG5iaXRzID0gMyAqIGxvZzIobik7CgppbnQgRCwgciwgaXRvcltEbWF4XSA9IHt9LCBydG9pW0RtYXhdOwpsb25nIGxvbmcgZFtuXTsKCmlubGluZSBsb25nIGxvbmcgY3ViZShpbnQgaSkKewogICAgcmV0dXJuIChsb25nIGxvbmcpaSAqIGkgKiBpOwp9CgppbmxpbmUgaW50IGF0b2IoaW50IGEpCnsKICAgIGludCByYjsKICAgIGlmICgocmIgPSBpdG9yW2FdIC0gcikgPCAwKSByYiArPSBEOwogICAgcmV0dXJuIHJ0b2lbcmJdOwp9CgppbmxpbmUgdm9pZCBQcmludFNvbHV0aW9uKGxvbmcgbG9uZyAqcCkKewogICAgaW50IGEsIGI7CiAgICBib29sIGZpcnN0ID0gdHJ1ZTsKCiAgICBjb3V0IDw8ICpwIDw8ICI6ICI7CiAgICBmb3IgKGEgPSAyOyBhIDw9IG47IGErKykgewogICAgICAgIGlmIChiID0gYXRvYihhKSwgYiA9PSAwIHx8IGIgPj0gYSkgY29udGludWU7CiAgICAgICAgaWYgKCpwICE9IGN1YmUoYSkgLSBjdWJlKGIpKSBjb250aW51ZTsKICAgICAgICBjb3V0IDw8IChmaXJzdCA/IGZpcnN0ID0gZmFsc2UsICIoIiA6ICIsICgiKSA8PCBhIDw8ICIsICIgPDwgYiA8PCAiKSI7CiAgICB9CiAgICBjb3V0IDw8IGVuZGw7Cn0KCnZvaWQgRmluZER1cGxpY2F0ZXMobG9uZyBsb25nICpwLCBsb25nIGxvbmcgKnEsIGludCBkZXB0aCkKewogICAgaWYgKHEgLSBwIDwgbSkgcmV0dXJuOwogICAgaWYgKGRlcHRoIDwgMCkgcmV0dXJuIFByaW50U29sdXRpb24ocCk7CgogICAgbG9uZyBsb25nIG1hc2sgPSAxTEwgPDwgZGVwdGg7CiAgICBsb25nIGxvbmcgKlAgPSBwYXJ0aXRpb24ocCwgcSwgWyZdKGxvbmcgbG9uZyB4KSB7cmV0dXJuICEoeCAmIG1hc2spO30pOwoKICAgIEZpbmREdXBsaWNhdGVzKHAsIFAsIGRlcHRoIC0gMSk7CiAgICBGaW5kRHVwbGljYXRlcyhQLCBxLCBkZXB0aCAtIDEpOwp9CgppbnQgbWFpbih2b2lkKQp7CiAgICBpbnQgYSwgYiwgaTsKCiAgICBmb3IgKEQgPSBuICsgMTsgRCA8PSBEbWF4OyBEKyspIHsKICAgICAgICBmaWxsKHJ0b2ksIHJ0b2kgKyBELCAwKTsKICAgICAgICBmb3IgKGkgPSAxOyBpIDw9IG47IGkrKykgewogICAgICAgICAgICByID0gY3ViZShpKSAlIEQ7CiAgICAgICAgICAgIGlmIChydG9pW3JdKSBicmVhazsgZWxzZSBydG9pW3JdID0gaTsKICAgICAgICB9CiAgICAgICAgaWYgKGkgPiBuKSBicmVhazsKICAgIH0KICAgIGlmIChEID4gRG1heCkgcmV0dXJuIGNvdXQgPDwgIkQgbm90IGZvdW5kLiIgPDwgZW5kbCwgMTsKICAgIGZvciAociA9IDA7IHIgPCBEOyByKyspIGl0b3JbcnRvaVtyXV0gPSByOwoKICAgIGZvciAociA9IDE7IHIgPCBEOyByKyspIHsKICAgICAgICBmb3IgKGkgPSAwLCBhID0gMjsgYSA8PSBuOyBhKyspIHsKICAgICAgICAgICAgaWYgKGIgPSBhdG9iKGEpLCBiID09IDAgfHwgYiA+PSBhKSBjb250aW51ZTsKICAgICAgICAgICAgZFtpKytdID0gY3ViZShhKSAtIGN1YmUoYik7CiAgICAgICAgfQogICAgICAgIEZpbmREdXBsaWNhdGVzKGQsIGQgKyBpLCBuYml0cyk7CiAgICB9CiAgICByZXR1cm4gMDsKfQ==