// CubeDifferenceQuintuplets9.cpp - 2つの自然数の3乗差が等しくなる5つ組 (mod・再帰ビット二分版)
#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, itor[Dmax] = {}, rtoi[Dmax];
int A[n], B[n], P[n];
long long d[n];
inline void PrintSolution(int *p, int*q)
{
cout << d[*p] << ": ";
sort(p, q, [](int x, int y) {return A[x] < A[y];});
for_each(p, q, [&](int &x) {
cout << (&x > p ? ", (" : "(") << A[x] << ", " << B[x] << ")";
});
cout << endl;
}
void FindDuplicates(int *p, int *q, int depth)
{
if (q - p < m) return;
if (depth < 0) return PrintSolution(p, q);
int *P = p, *Q = q;
long long mask = 1LL << depth;
for (q = p; q < Q; q++) if (!(d[*q] & mask)) p != q ? swap(*p++, *q) : (void)p++;
FindDuplicates(P, p, depth - 1);
FindDuplicates(p, Q, depth - 1);
}
int main(void)
{
int a, b, i, r, ra, rb;
for (D = n + 1; D <= Dmax; D++) {
fill(rtoi, rtoi + D, 0);
for (i = 1; i <= n; i++) {
r = (long long)i * i * 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++) {
ra = itor[a];
if ((rb = ra - r) < 0) rb += D;
if (b = rtoi[rb], b == 0 || b >= a) continue;
A[i] = a;
B[i] = b;
d[i] = (long long)a * a * a - (long long)b * b * b;
P[i] = i;
i++;
}
FindDuplicates(P, P + i, nbits);
}
return 0;
}
Ly8gQ3ViZURpZmZlcmVuY2VRdWludHVwbGV0czkuY3BwIC0gMuOBpOOBruiHqueEtuaVsOOBrjPkuZflt67jgYznrYnjgZfjgY/jgarjgos144Gk57WEIChtb2Tjg7vlho3luLDjg5Pjg4Pjg4jkuozliIbniYgpCgojaW5jbHVkZSA8aW9zdHJlYW0+CiNpbmNsdWRlIDxhbGdvcml0aG0+CiNpbmNsdWRlIDxjbWF0aD4KCnVzaW5nIG5hbWVzcGFjZSBzdGQ7Cgpjb25zdCBpbnQgbiA9IDUwMDA7CmNvbnN0IGludCBtID0gNTsKY29uc3QgaW50IERtYXggPSBuICsgMTAwOwpjb25zdCBpbnQgbmJpdHMgPSAzICogbG9nMihuKTsKCmludCBELCBpdG9yW0RtYXhdID0ge30sIHJ0b2lbRG1heF07CmludCBBW25dLCBCW25dLCBQW25dOwpsb25nIGxvbmcgZFtuXTsKCmlubGluZSB2b2lkIFByaW50U29sdXRpb24oaW50ICpwLCBpbnQqcSkKewogICAgY291dCA8PCBkWypwXSA8PCAiOiAiOwogICAgc29ydChwLCBxLCBbXShpbnQgeCwgaW50IHkpIHtyZXR1cm4gQVt4XSA8IEFbeV07fSk7CiAgICBmb3JfZWFjaChwLCBxLCBbJl0oaW50ICZ4KSB7CiAgICAgICAgY291dCA8PCAoJnggPiBwID8gIiwgKCIgOiAiKCIpIDw8IEFbeF0gPDwgIiwgIiA8PCBCW3hdIDw8ICIpIjsKICAgIH0pOwogICAgY291dCA8PCBlbmRsOwp9Cgp2b2lkIEZpbmREdXBsaWNhdGVzKGludCAqcCwgaW50ICpxLCBpbnQgZGVwdGgpCnsKICAgIGlmIChxIC0gcCA8IG0pIHJldHVybjsKICAgIGlmIChkZXB0aCA8IDApIHJldHVybiBQcmludFNvbHV0aW9uKHAsIHEpOwoKICAgIGludCAqUCA9IHAsICpRID0gcTsKICAgIGxvbmcgbG9uZyBtYXNrID0gMUxMIDw8IGRlcHRoOwoKICAgIGZvciAocSA9IHA7IHEgPCBROyBxKyspIGlmICghKGRbKnFdICYgbWFzaykpIHAgIT0gcSA/IHN3YXAoKnArKywgKnEpIDogKHZvaWQpcCsrOwoKICAgIEZpbmREdXBsaWNhdGVzKFAsIHAsIGRlcHRoIC0gMSk7CiAgICBGaW5kRHVwbGljYXRlcyhwLCBRLCBkZXB0aCAtIDEpOwp9CgppbnQgbWFpbih2b2lkKQp7CiAgICBpbnQgYSwgYiwgaSwgciwgcmEsIHJiOwoKICAgIGZvciAoRCA9IG4gKyAxOyBEIDw9IERtYXg7IEQrKykgewogICAgICAgIGZpbGwocnRvaSwgcnRvaSArIEQsIDApOwogICAgICAgIGZvciAoaSA9IDE7IGkgPD0gbjsgaSsrKSB7CiAgICAgICAgICAgIHIgPSAobG9uZyBsb25nKWkgKiBpICogaSAlIEQ7CiAgICAgICAgICAgIGlmIChydG9pW3JdKSBicmVhazsgZWxzZSBydG9pW3JdID0gaTsKICAgICAgICB9CiAgICAgICAgaWYgKGkgPiBuKSBicmVhazsKICAgIH0KICAgIGlmIChEID4gRG1heCkgcmV0dXJuIGNvdXQgPDwgIkQgbm90IGZvdW5kLiIgPDwgZW5kbCwgMTsKICAgIGZvciAociA9IDA7IHIgPCBEOyByKyspIGl0b3JbcnRvaVtyXV0gPSByOwoKICAgIGZvciAociA9IDE7IHIgPCBEOyByKyspIHsKICAgICAgICBmb3IgKGkgPSAwLCBhID0gMjsgYSA8PSBuOyBhKyspIHsKICAgICAgICAgICAgcmEgPSBpdG9yW2FdOwogICAgICAgICAgICBpZiAoKHJiID0gcmEgLSByKSA8IDApIHJiICs9IEQ7CiAgICAgICAgICAgIGlmIChiID0gcnRvaVtyYl0sIGIgPT0gMCB8fCBiID49IGEpIGNvbnRpbnVlOwogICAgICAgICAgICBBW2ldID0gYTsKICAgICAgICAgICAgQltpXSA9IGI7CiAgICAgICAgICAgIGRbaV0gPSAobG9uZyBsb25nKWEgKiBhICogYSAtIChsb25nIGxvbmcpYiAqIGIgKiBiOwogICAgICAgICAgICBQW2ldID0gaTsKICAgICAgICAgICAgaSsrOwogICAgICAgIH0KICAgICAgICBGaW5kRHVwbGljYXRlcyhQLCBQICsgaSwgbmJpdHMpOwogICAgfQogICAgcmV0dXJuIDA7Cn0=