/* by Cristian Francu on 2019-12-19 C source code that generates the Nth element of A005228. Runs in O(sqrt(N)) time and uses O(sqrt(N)) memory. Works for N up to 2 billion, but can be made to run up to much higher values using either 128 bit integers, or large numbers. Description: - We generate elements linearly, storing them in a queue, as to know when to skip them. When skipping an element we take it out of the queue. - We keep track of how many elements we can generate until we reach the last element in the queue (to skip). - We stop with linear generation when we can generate at least N elements. In other words, the last element in the queue minus one is greater or equal to the desired Nth element. - This way we will generate about sqrt(N) elements. - At this point the queue will contain about sqrt(N) elements. - All the above uses integer computations (four bytes). - At this point we use a formula to compute the Nth element: it is the sum of a sequence of consecutive numbers. - We adjust that summation, subtracting the elements in the queue (except the last one). - This last step is also sqrt(N) time since that is the length of the queue. - This last step uses long long subtractions (8 bytes). */ #include #define MAXQ 65536 int used[MAXQ]; int main() { int n, i, l, first, last, inqueue, xc, qlen, maxq; long long x; scanf( "%d", &n ); used[first = last = 0] = -1; // sentinel xc = 1; l = 1; inqueue = 0; i = n - 1; maxq = 0; while ( i > inqueue ) { l++; if ( l == used[first] ) { first = (first + 1) % MAXQ; l++; } inqueue += l - 1; used[last] = xc + l; last = (last + 1) % MAXQ; if ( (last - first + MAXQ) % MAXQ > maxq ) maxq = (last - first + MAXQ) % MAXQ; xc += l; i--; inqueue--; } // This is the second stage, summation and subtraction of elements in queue. x = xc; if ( i > 0 ) { /* We have i more elements to compute starting with xc to which we have to add l+1 l+2 ... and so on. However, we will need to add i such numbers plus extra elements. How many? The number of elements in the queue minus one (these are the elements we will subtract). So, in fact, we will add: l+1 l+2 ... l+qlen-1 */ qlen = (last - first + MAXQ) % MAXQ; x += (2 * l + i + qlen) * (long long)(i + qlen - 1) / 2; // Then we subtract all elements in the queue, except the last one. while ( --qlen ) { x -= used[first]; first = (first + 1) % MAXQ; } } printf( "%lld\n", x ); return 0; }