/* #define DEBUG */
/* #define DEBUG_VOMIT */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>
#define N_MAX 2500000
#define X_LIMIT 10000000000UL /*10000000UL*/
#define DATA_MAX 4294967295UL /* heap_n の初期値 > X_LIMIT */
#define EQUAL 10 /* > 5 */ /* 求める組み合わせの数 */
typedef uint64_t DATA;
typedef uint64_t PARA;
/* f(n, k) = (n + k)^3 - n^3 とするとき、
* f(n + 1, 1) = f(n, 1) + 6 * (n + 1) ... 3 乗差(a) の生成
* f(n, k + 1) = f(n, k) + f(n + k, 1) ... 3 乗差(b) の生成
*/
static DATA d1[N_MAX]; /* 3 乗差(a): d1[n] = f(n, 1) */
static DATA d[N_MAX]; /* 3 乗差(b): d[n] = f(n, p[n]) */
static PARA p[N_MAX];
struct {
DATA n;
PARA a;
PARA b;
} output_stack[EQUAL];
static int f_verbose = 0; /* verbose mode */
/* proto-type */
void init_heap(void);
void put_heap(DATA n, PARA a, PARA b);
void get_heap(DATA *n, PARA *a, PARA *b);
void vomit_heap(void);
void findX(int);
/* DATA top_heap(void); */
static DATA heap_n[N_MAX];
#define top_heap() heap_n[1]
int main(int argc, char **argv)
{
time_t start, stop;
if (argc == 2 && *argv[1] == '-' && *(argv[1] + 1) == 'v')
f_verbose = 1;
findX(4);
findX(5);
fprintf(stderr
, "(time: %ld sec.)\n", stop
- start
); return 0;
}
void findX(int iEQUAL) {
PARA max, i, a, b; /* 配列パラメータ系 */
DATA diff, new, res, n; /* 3 乗差系 */
int sp, j;
/* 初期化 */
d[1] = d1[1] = 7;
max = p[1] = 1;
diff = 6;
for (i = 2; i < N_MAX; i++) {
d[i] = 0;
p[i] = 0;
}
/* heap 初期化 */
init_heap();
put_heap(d[1], 1, 1);
for (;;) {
/* 新たに 3 乗差(a) を生成 -> new */
diff += 6L;
new = d1[max] + diff;
max++;
d1[max] = new;
d[max] = new;
p[max] = 1;
/* 終了条件 1 */
if (new > X_LIMIT) {
fprintf(stderr
, "3 乗差が範囲(~%ld)を超えた.\n", X_LIMIT
); vomit_heap();
}
/* 終了条件 2 */
if (max > N_MAX) {
fprintf(stderr
, "配列パラメータが範囲を超えた(max).n"); vomit_heap();
}
/* new を heap に積み上げる */
put_heap(new, 1, max);
/* heap から new 以下の 3 乗差 (組み合わせ確定) を取り出す */
while((res = top_heap()) < new) {
sp = 0;
while (res == top_heap()) {
get_heap(&n, &a, &b);
output_stack[sp].n = n;
output_stack[sp].a = a;
output_stack[sp].b = b;
sp++;
}
if (f_verbose) { /* verbose mode */
if (sp >= 2) {
for (j = 0; j < sp; j++)
output_stack[j].a + output_stack[j].b,
output_stack[j].b);
}
}
/* 終了条件 3: 解発見 */
if (sp == iEQUAL)
goto label_soluted;
}
/* 3 乗差(b) を生成 */
for (i = 1; i < max; i++) {
if (new > d[i]) {
d[i] = d[i] + d1[i + p[i]];
p[i]++;
put_heap(d[i], i, p[i]);
}
}
}
label_soluted:
printf("%ld\n", output_stack
[0].
n); for (i = 0; i < iEQUAL; i++) {
PARA a1, a2;
a1 = output_stack[i].a + output_stack[i].b;
a2 = output_stack[i].a;
printf("= %u^3 - %u^3\n", a1
, a2
); }
}
/* =========================================== */
/* static DATA heap_n[N_MAX]; */
static PARA heap_a[N_MAX];
static PARA heap_b[N_MAX];
void init_heap(void) {
PARA i;
for (i = 0; i < N_MAX; i++)
heap_n[i] = DATA_MAX;
return;
}
void put_heap(DATA n, PARA a, PARA b) {
PARA child, parent, tmp_p;
DATA tmp_d;
#ifdef DEBUG
fprintf(stderr
, " %ld, %u, %u\n", n
, a
, b
); #endif
child = 1;
while (heap_n[child] < DATA_MAX)
child++;
heap_n[child] = n;
heap_a[child] = a;
heap_b[child] = b;
while (parent = child >> 1,
(parent >= 1 && heap_n[child] < heap_n[parent])) {
tmp_d = heap_n[child]; /* swap heap_n */
heap_n[child] = heap_n[parent];
heap_n[parent] = tmp_d;
tmp_p = heap_a[child]; /* swap heap_a */
heap_a[child] = heap_a[parent];
heap_a[parent] = tmp_p;
tmp_p = heap_b[child]; /* swap heap_b */
heap_b[child] = heap_b[parent];
heap_b[parent] = tmp_p;
#ifdef DEBUG
fprintf(stderr
, "<put_heap> exchange(%u, %u)\n", child
, parent
); #endif
}
#ifdef DEBUG_VOMIT
vomit_heap();
#endif
return;
}
void get_heap(DATA *n, PARA *a, PARA *b) {
PARA child, parent;
#ifdef DEBUG
#endif
*n = heap_n[1];
*a = heap_a[1];
*b = heap_b[1];
#ifdef DEBUG
fprintf(stderr
, "-> %ld, %u, %u\n", *n
, *a
, *b
); #endif
parent = 1;
while (heap_n[parent] != DATA_MAX) {
child = parent << 1;
if (heap_n[child] > heap_n[child + 1])
child++;
heap_n[parent] = heap_n[child];
heap_a[parent] = heap_a[child];
heap_b[parent] = heap_b[child];
parent = child;
}
#ifdef DEBUG_VOMIT
vomit_heap();
#endif
return;
}
/*
DATA top_heap(void) {
return heap_n[1];
}
*/
#define VOMIT_LEVEL 15
void vomit_heap(void) {
PARA max, i;
for (max = N_MAX - 1; heap_n[max] == DATA_MAX && max > 0; max--)
;
if (max < VOMIT_LEVEL) max = VOMIT_LEVEL;
i = 0;
while(i < max) {
fprintf(stderr
, "heap[%u] %ld: (%u, %u) \n", i,heap_n[i],heap_a[i],heap_b[i]);
i++;
}
return;
}
/* end */
LyogI2RlZmluZSBERUJVRyAqLyAKLyogI2RlZmluZSBERUJVR19WT01JVCAqLwoKI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHRpbWUuaD4KI2luY2x1ZGUgPHN0ZGludC5oPgoKI2RlZmluZSBOX01BWCAyNTAwMDAwCiNkZWZpbmUgWF9MSU1JVCAgMTAwMDAwMDAwMDBVTCAvKjEwMDAwMDAwVUwqLwojZGVmaW5lIERBVEFfTUFYICA0Mjk0OTY3Mjk1VUwgCS8qIGhlYXBfbiDjga7liJ3mnJ/lgKQgPiBYX0xJTUlUICovCiNkZWZpbmUgRVFVQUwgMTAgLyogPiA1ICovIC8qIOaxguOCgeOCi+e1hOOBv+WQiOOCj+OBm+OBruaVsCAqLwoKdHlwZWRlZiB1aW50NjRfdCBEQVRBOwp0eXBlZGVmIHVpbnQ2NF90IFBBUkE7CgovKiBmKG4sIGspID0gKG4gKyBrKV4zIC0gbl4zIOOBqOOBmeOCi+OBqOOBjeOAgQogKiAgICBmKG4gKyAxLCAxKSA9IGYobiwgMSkgKyA2ICogKG4gKyAxKSAuLi4gMyDkuZflt64oYSkg44Gu55Sf5oiQCiAqICAgIGYobiwgayArIDEpID0gZihuLCBrKSArIGYobiArIGssIDEpIC4uLiAzIOS5l+W3rihiKSDjga7nlJ/miJAKICovCgpzdGF0aWMgREFUQSBkMVtOX01BWF07CS8qIDMg5LmX5beuKGEpOiBkMVtuXSA9IGYobiwgMSkgKi8Kc3RhdGljIERBVEEgZFtOX01BWF07CS8qIDMg5LmX5beuKGIpOiBkW25dID0gZihuLCBwW25dKSAqLwpzdGF0aWMgUEFSQSBwW05fTUFYXTsKCnN0cnVjdCB7CglEQVRBIG47CglQQVJBIGE7CglQQVJBIGI7Cn0gb3V0cHV0X3N0YWNrW0VRVUFMXTsKCnN0YXRpYyBpbnQgZl92ZXJib3NlID0gMDsJCS8qIHZlcmJvc2UgbW9kZSAqLwoKLyogcHJvdG8tdHlwZSAqLwp2b2lkIGluaXRfaGVhcCh2b2lkKTsKdm9pZCBwdXRfaGVhcChEQVRBIG4sIFBBUkEgYSwgUEFSQSBiKTsKdm9pZCBnZXRfaGVhcChEQVRBICpuLCBQQVJBICphLCBQQVJBICpiKTsKdm9pZCB2b21pdF9oZWFwKHZvaWQpOwp2b2lkIGZpbmRYKGludCk7CgovKiBEQVRBIHRvcF9oZWFwKHZvaWQpOyAqLwpzdGF0aWMgREFUQSBoZWFwX25bTl9NQVhdOwojZGVmaW5lIHRvcF9oZWFwKCkgaGVhcF9uWzFdCgppbnQgbWFpbihpbnQgYXJnYywgY2hhciAqKmFyZ3YpCnsKICB0aW1lX3Qgc3RhcnQsIHN0b3A7CgogIHRpbWUoJnN0YXJ0KTsKICBpZiAoYXJnYyA9PSAyICYmICphcmd2WzFdID09ICctJyAmJiAqKGFyZ3ZbMV0gKyAxKSA9PSAndicpCiAgICBmX3ZlcmJvc2UgPSAxOwogIAogIGZpbmRYKDQpOwogIGZpbmRYKDUpOyAgCgogIHRpbWUoJnN0b3ApOwogIGZwcmludGYoc3RkZXJyLCAiKHRpbWU6ICVsZCBzZWMuKVxuIiwgc3RvcCAtIHN0YXJ0KTsKICByZXR1cm4gMDsKfQoKdm9pZCBmaW5kWChpbnQgaUVRVUFMKSB7CiAgUEFSQSBtYXgsIGksIGEsIGI7IC8qIOmFjeWIl+ODkeODqeODoeODvOOCv+ezuyAqLwogIERBVEEgZGlmZiwgbmV3LCByZXMsIG47IC8qIDMg5LmX5beu57O7ICovCiAgaW50IHNwLCBqOwoKICAvKiDliJ3mnJ/ljJYgKi8KICBkWzFdID0gZDFbMV0gPSA3OwogIG1heCA9IHBbMV0gPSAxOwogIGRpZmYgPSA2OwogIGZvciAoaSA9IDI7IGkgPCBOX01BWDsgaSsrKSB7CiAgICBkW2ldID0gMDsKICAgIHBbaV0gPSAwOwogIH0KICAKICAvKiBoZWFwIOWIneacn+WMliAqLwogIGluaXRfaGVhcCgpOwogIHB1dF9oZWFwKGRbMV0sIDEsIDEpOwogIAogIGZvciAoOzspIHsKICAgIC8qIOaWsOOBn+OBqyAzIOS5l+W3rihhKSDjgpLnlJ/miJAgLT4gbmV3ICovCiAgICBkaWZmICs9IDZMOwogICAgbmV3ID0gZDFbbWF4XSArIGRpZmY7CiAgICBtYXgrKzsKICAgIGQxW21heF0gPSBuZXc7CiAgICBkW21heF0gPSBuZXc7CiAgICBwW21heF0gPSAxOwogICAgCiAgICAvKiDntYLkuobmnaHku7YgMSAqLwogICAgaWYgKG5ldyA+IFhfTElNSVQpIHsKICAgICAgZnByaW50ZihzdGRlcnIsICIzIOS5l+W3ruOBjOevhOWbsijvvZ4lbGQp44KS6LaF44GI44GfLlxuIiwgWF9MSU1JVCk7CiAgICAgIHZvbWl0X2hlYXAoKTsKICAgICAgZXhpdCgwKTsKICAgIH0KICAgIC8qIOe1guS6huadoeS7tiAyICovCiAgICBpZiAobWF4ID4gTl9NQVgpIHsKICAgICAgZnByaW50ZihzdGRlcnIsICLphY3liJfjg5Hjg6njg6Hjg7zjgr/jgYznr4Tlm7LjgpLotoXjgYjjgZ8obWF4KS5uIik7CiAgICAgIHZvbWl0X2hlYXAoKTsKICAgICAgZXhpdCgwKTsKICAgIH0KICAgIC8qIG5ldyDjgpIgaGVhcCDjgavnqY3jgb/kuIrjgZLjgosgKi8KICAgIHB1dF9oZWFwKG5ldywgMSwgbWF4KTsKICAgIAogICAgLyogaGVhcCDjgYvjgokgbmV3IOS7peS4i+OBriAzIOS5l+W3riAo57WE44G/5ZCI44KP44Gb56K65a6aKSDjgpLlj5bjgorlh7rjgZkgKi8KICAgIHdoaWxlKChyZXMgPSB0b3BfaGVhcCgpKSA8IG5ldykgewogICAgICBzcCA9IDA7CiAgICAgIHdoaWxlIChyZXMgPT0gdG9wX2hlYXAoKSkgewogICAgICAgIGdldF9oZWFwKCZuLCAmYSwgJmIpOwogICAgICAgIG91dHB1dF9zdGFja1tzcF0ubiA9IG47CiAgICAgICAgb3V0cHV0X3N0YWNrW3NwXS5hID0gYTsKICAgICAgICBvdXRwdXRfc3RhY2tbc3BdLmIgPSBiOwogICAgICAgIHNwKys7CiAgICAgIH0KICAgICAgaWYgKGZfdmVyYm9zZSkgeyAvKiB2ZXJib3NlIG1vZGUgKi8KICAgICAgICBpZiAoc3AgPj0gMikgewogICAgICAgICAgcHJpbnRmKCIlbGQgKCVkKTogIiwgbiwgc3ApOwogICAgICAgICAgZm9yIChqID0gMDsgaiA8IHNwOyBqKyspCiAgICAgICAgICAgIHByaW50ZigiKCV1LCV1KSAgIiwKICAgICAgICAgICAgICAgICAgIG91dHB1dF9zdGFja1tqXS5hICsgb3V0cHV0X3N0YWNrW2pdLmIsCiAgICAgICAgICAgICAgICAgICBvdXRwdXRfc3RhY2tbal0uYik7CiAgICAgICAgICBwdXRjaGFyKCdcbicpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKiDntYLkuobmnaHku7YgMzog6Kej55m66KaLICovCiAgICAgIGlmIChzcCA9PSBpRVFVQUwpCiAgICAgICAgZ290byBsYWJlbF9zb2x1dGVkOwogICAgfQogICAgLyogMyDkuZflt64oYikg44KS55Sf5oiQICovCiAgICBmb3IgKGkgPSAxOyBpIDwgbWF4OyBpKyspIHsKICAgICAgaWYgKG5ldyA+IGRbaV0pIHsKICAgICAgICBkW2ldID0gZFtpXSArIGQxW2kgKyBwW2ldXTsKICAgICAgICBwW2ldKys7CiAgICAgICAgcHV0X2hlYXAoZFtpXSwgaSwgcFtpXSk7CiAgICAgIH0KICAgIH0KICB9CiAgCmxhYmVsX3NvbHV0ZWQ6CiAgcHJpbnRmKCJzb2x1dGlvbiA6XG4iKTsKICBwcmludGYoIiVsZFxuIiwgb3V0cHV0X3N0YWNrWzBdLm4pOwogIGZvciAoaSA9IDA7IGkgPCBpRVFVQUw7IGkrKykgewogICAgUEFSQSBhMSwgYTI7CiAgICBhMSA9IG91dHB1dF9zdGFja1tpXS5hICsgb3V0cHV0X3N0YWNrW2ldLmI7CiAgICBhMiA9IG91dHB1dF9zdGFja1tpXS5hOwogICAgcHJpbnRmKCI9ICV1XjMgLSAldV4zXG4iLCBhMSwgYTIpOwogIH0KfQoKLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwovKiBzdGF0aWMgREFUQSBoZWFwX25bTl9NQVhdOyAqLwpzdGF0aWMgUEFSQSBoZWFwX2FbTl9NQVhdOwpzdGF0aWMgUEFSQSBoZWFwX2JbTl9NQVhdOwoKdm9pZCBpbml0X2hlYXAodm9pZCkgewogIFBBUkEgaTsKCiAgZm9yIChpID0gMDsgaSA8IE5fTUFYOyBpKyspCiAgICBoZWFwX25baV0gPSBEQVRBX01BWDsKICByZXR1cm47Cn0KCnZvaWQgcHV0X2hlYXAoREFUQSBuLCBQQVJBIGEsIFBBUkEgYikgewogIFBBUkEgY2hpbGQsIHBhcmVudCwgdG1wX3A7CiAgREFUQSB0bXBfZDsKICAKI2lmZGVmIERFQlVHCiAgZnByaW50ZihzdGRlcnIsICI8cHV0X2hlYXA+Iik7CiAgZnByaW50ZihzdGRlcnIsICIJJWxkLCAldSwgJXVcbiIsIG4sIGEsIGIpOwojZW5kaWYKICBjaGlsZCA9IDE7CiAgd2hpbGUgKGhlYXBfbltjaGlsZF0gPCBEQVRBX01BWCkKICAgIGNoaWxkKys7CiAgaGVhcF9uW2NoaWxkXSA9IG47CiAgaGVhcF9hW2NoaWxkXSA9IGE7CiAgaGVhcF9iW2NoaWxkXSA9IGI7CiAgd2hpbGUgKHBhcmVudCA9IGNoaWxkID4+IDEsCiAgICAgICAgIChwYXJlbnQgPj0gMSAmJiBoZWFwX25bY2hpbGRdIDwgaGVhcF9uW3BhcmVudF0pKSB7CiAgICB0bXBfZCA9IGhlYXBfbltjaGlsZF07CQkJLyogc3dhcCBoZWFwX24gKi8KICAgIGhlYXBfbltjaGlsZF0gPSBoZWFwX25bcGFyZW50XTsKICAgIGhlYXBfbltwYXJlbnRdID0gdG1wX2Q7CiAgICB0bXBfcCA9IGhlYXBfYVtjaGlsZF07CQkJLyogc3dhcCBoZWFwX2EgKi8KICAgIGhlYXBfYVtjaGlsZF0gPSBoZWFwX2FbcGFyZW50XTsKICAgIGhlYXBfYVtwYXJlbnRdID0gdG1wX3A7CiAgICB0bXBfcCA9IGhlYXBfYltjaGlsZF07CQkJLyogc3dhcCBoZWFwX2IgKi8KICAgIGhlYXBfYltjaGlsZF0gPSBoZWFwX2JbcGFyZW50XTsKICAgIGhlYXBfYltwYXJlbnRdID0gdG1wX3A7CiNpZmRlZiBERUJVRwogICAgZnByaW50ZihzdGRlcnIsICI8cHV0X2hlYXA+IGV4Y2hhbmdlKCV1LCAldSlcbiIsIGNoaWxkLCBwYXJlbnQpOwojZW5kaWYKICB9CiNpZmRlZiBERUJVR19WT01JVAogIHZvbWl0X2hlYXAoKTsKI2VuZGlmCiAgcmV0dXJuOwp9Cgp2b2lkIGdldF9oZWFwKERBVEEgKm4sIFBBUkEgKmEsIFBBUkEgKmIpIHsKICBQQVJBIGNoaWxkLCBwYXJlbnQ7CiAgCiNpZmRlZiBERUJVRwogIGZwcmludGYoc3RkZXJyLCAiPGdldF9oZWFwPiIpOwojZW5kaWYKICAqbiA9IGhlYXBfblsxXTsKICAqYSA9IGhlYXBfYVsxXTsKICAqYiA9IGhlYXBfYlsxXTsKI2lmZGVmIERFQlVHCiAgZnByaW50ZihzdGRlcnIsICItPgklbGQsICV1LCAldVxuIiwgKm4sICphLCAqYik7CiNlbmRpZgogIHBhcmVudCA9IDE7CiAgd2hpbGUgKGhlYXBfbltwYXJlbnRdICE9IERBVEFfTUFYKSB7CiAgICBjaGlsZCA9IHBhcmVudCA8PCAxOwogICAgaWYgKGhlYXBfbltjaGlsZF0gPiBoZWFwX25bY2hpbGQgKyAxXSkKICAgICAgY2hpbGQrKzsKICAgIGhlYXBfbltwYXJlbnRdID0gaGVhcF9uW2NoaWxkXTsKICAgIGhlYXBfYVtwYXJlbnRdID0gaGVhcF9hW2NoaWxkXTsKICAgIGhlYXBfYltwYXJlbnRdID0gaGVhcF9iW2NoaWxkXTsKICAgIHBhcmVudCA9IGNoaWxkOwogIH0KI2lmZGVmIERFQlVHX1ZPTUlUCiAgdm9taXRfaGVhcCgpOwojZW5kaWYKICByZXR1cm47Cn0KCi8qCkRBVEEgdG9wX2hlYXAodm9pZCkgewoJcmV0dXJuIGhlYXBfblsxXTsKfQoqLwoKI2RlZmluZSBWT01JVF9MRVZFTCAxNQoKdm9pZCB2b21pdF9oZWFwKHZvaWQpIHsKICBQQVJBIG1heCwgaTsKICAKICBmb3IgKG1heCA9IE5fTUFYIC0gMTsgaGVhcF9uW21heF0gPT0gREFUQV9NQVggJiYgbWF4ID4gMDsgbWF4LS0pCiAgICA7CiAgZnByaW50ZihzdGRlcnIsICJ2b21pdF9oZWFwOlxuIik7CiAgaWYgKG1heCA8IFZPTUlUX0xFVkVMKSBtYXggPSBWT01JVF9MRVZFTDsKICBpID0gMDsKICB3aGlsZShpIDwgbWF4KSB7CiAgICBmcHJpbnRmKHN0ZGVyciwgImhlYXBbJXVdICVsZDogKCV1LCAldSkgXG4iLAogICAgICAgICAgICBpLGhlYXBfbltpXSxoZWFwX2FbaV0saGVhcF9iW2ldKTsKICAgIGkrKzsKICB9CiAgcmV0dXJuOwp9CgovKiBlbmQgKi8K