#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

static const int MultiplyDeBruijnBitPosition[32] = {
    0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
    8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
};

static const uint32_t PowersOf10[] = {
    1, 10, 100, 1000, 10000, 100000,
    1000000, 10000000, 100000000, 1000000000
};

static const uint32_t MaxWithDigits[] = {
    0, 9, 99, 999, 9999, 99999,
    999999, 9999999, 99999999, 999999999
};

static const uint32_t MinWithDigits[] = {
    0, 0, 10, 100, 1000, 10000,
    100000, 1000000, 10000000, 100000000
};

typedef struct _stringlist {
    char *v;
    struct _stringlist *next;
} stringlist;

inline int IntegerLogBase2(uint32_t v) {
    v |= v >> 1;
    v |= v >> 2;
    v |= v >> 4;
    v |= v >> 8;
    v |= v >> 16;
    return MultiplyDeBruijnBitPosition[(uint32_t) (v * 0x07C4ACDDU) >> 27];
}

inline int IntegerLogBase10(uint32_t v) {
    int t;
    t = (IntegerLogBase2(v) + 1) * 1233 >> 12;
    return t - (v < PowersOf10[t]);
}

inline int IntegerDigitsBase10(uint32_t v) {
    return (v == 0) ? 1 : IntegerLogBase10(v) + 1;
}

inline int Itoa(uint32_t v, char *b) {
    int i, l;
    i = l = IntegerDigitsBase10(v);
    b[i] = 0;
    do {
        i--;
        b[i] = v % 10 + '0';
        v /= 10;
    } while (i != 0);
    return l;
}

inline int range_digits(uint32_t start, uint32_t end) {
    int s = IntegerDigitsBase10(start);
    int e = IntegerDigitsBase10(end);
    int count = 0;
    if (s == e) {
        count += (end - start + 1) * s;
    } else {
        count += (MaxWithDigits[s] - start + 1) * s;
        count += (end - MinWithDigits[e] + 1) * e;
        s++;
        while (s != e) {
            count += (MaxWithDigits[s] - MinWithDigits[s] + 1) * s;
            s++;
        }
    }
    return count;
}

stringlist *range_to_stringlist(uint32_t start, uint32_t end) {
    size_t count = end - start + 1;
    stringlist *all = malloc(sizeof(stringlist) * count);
    char *chrbuf = malloc(range_digits(start, end) + count);
    uint32_t i;
    for (i = 0; start + i <= end; i++) {
        all[i].v = chrbuf;
        all[i].next = all + i + 1;
        chrbuf += Itoa(start + i, chrbuf) + 1;
    }
    all[i - 1].next = 0;
    return all;
}

size_t stringlist_strlen(stringlist *s) {
    size_t l = 0;
    while (s != NULL) {
        l += strlen(s->v);
        s = s->next;
    }
    return l;
}

void stringlist_to_str(stringlist *s, char *b) {
	size_t l;
    while (s != NULL) {
    	l = strlen(s->v);
        memcpy(b, s->v, l);
        b += l;
        s = s->next;
    }
    *b = 0;
}

int main() {
    stringlist *s;
    s = range_to_stringlist(0, 4999999);
    char *c = malloc(stringlist_strlen(s) + 1);
    stringlist_to_str(s, c);
    printf("%d", strlen(c));
    return 0;
}
