#include <cstdio>
#include <iostream>
#include <climits>
#include <sstream>
#include <algorithm>
#include <cstring>
#include <limits>
#include <ctime>
using namespace std;
struct progress_timer {
clock_t c;
progress_timer() : c(clock()) { }
int elapsed() {
return clock() - c;
}
~progress_timer() {
clock_t d = clock() - c;
cout << d / CLOCKS_PER_SEC << "."
<< (((d * 1000) / CLOCKS_PER_SEC) % 1000 / 100)
<< (((d * 1000) / CLOCKS_PER_SEC) % 100 / 10)
<< (((d * 1000) / CLOCKS_PER_SEC) % 10)
<< " s" << endl;
}
};
namespace user_voigt_timo {
const char digit_pairs[201] = {
"00010203040506070809"
"10111213141516171819"
"20212223242526272829"
"30313233343536373839"
"40414243444546474849"
"50515253545556575859"
"60616263646566676869"
"70717273747576777879"
"80818283848586878889"
"90919293949596979899"
};
std::string& itostr(int n, std::string& s)
{
if(n==0)
{
s="0";
return s;
}
int sign = -(n<0);
unsigned int val = (n^sign)-sign;
int size;
if(val>=10000)
{
if(val>=10000000)
{
if(val>=1000000000)
size=10;
else if(val>=100000000)
size=9;
else
size=8;
}
else
{
if(val>=1000000)
size=7;
else if(val>=100000)
size=6;
else
size=5;
}
}
else
{
if(val>=100)
{
if(val>=1000)
size=4;
else
size=3;
}
else
{
if(val>=10)
size=2;
else
size=1;
}
}
size -= sign;
s.resize(size);
char* c = &s[0];
if(sign)
*c='-';
c += size-1;
while(val>=100)
{
int pos = val % 100;
val /= 100;
memcpy(c-1, digit_pairs+2*pos, 2);
c-=2;
}
while(val>0)
{
*c--='0' + (val % 10);
val /= 10;
}
return s;
}
std::string& itostr(unsigned val, std::string& s)
{
if(val==0)
{
s="0";
return s;
}
int size;
if(val>=10000)
{
if(val>=10000000)
{
if(val>=1000000000)
size=10;
else if(val>=100000000)
size=9;
else
size=8;
}
else
{
if(val>=1000000)
size=7;
else if(val>=100000)
size=6;
else
size=5;
}
}
else
{
if(val>=100)
{
if(val>=1000)
size=4;
else
size=3;
}
else
{
if(val>=10)
size=2;
else
size=1;
}
}
s.resize(size);
char* c = &s[size-1];
while(val>=100)
{
int pos = val % 100;
val /= 100;
memcpy(c-1, digit_pairs+2*pos, 2);
c-=2;
}
while(val>0)
{
*c--='0' + (val % 10);
val /= 10;
}
return s;
}
template <typename T>
std::string itostr(T t) {
std::string ret;
itostr(t, ret);
return ret;
}
}
namespace hopman_fun {
template <typename T>
T reduce2(T v) {
T k = ((v * 410) >> 12) & 0x000F000F000F000Full;
return (((v - k * 10) << 8) + k);
}
template <typename T>
T reduce4(T v) {
T k = ((v * 10486) >> 20) & 0xFF000000FFull;
return reduce2(((v - k * 100) << 16) + (k));
}
typedef unsigned long long ull;
inline ull reduce8(ull v) {
ull k = ((v * 3518437209u) >> 45);
return reduce4(((v - k * 10000) << 32) + (k));
}
template <typename T>
std::string itostr(T o) {
union {
char str[16];
unsigned short u2[8];
unsigned u4[4];
unsigned long long u8[2];
};
unsigned v = o < 0 ? ~o + 1 : o;
u8[0] = (ull(v) * 3518437209u) >> 45;
u8[0] = (u8[0] * 28147497672ull);
u8[1] = v - u2[3] * 100000000;
u8[1] = reduce8(u8[1]);
char* f;
if (u2[3]) {
u2[3] = reduce2(u2[3]);
f = str + 6;
} else {
unsigned short* k = u4[2] ? u2 + 4 : u2 + 6;
f = *k ? (char*)k : (char*)(k + 1);
}
if (!*f) f++;
u4[1] |= 0x30303030;
u4[2] |= 0x30303030;
u4[3] |= 0x30303030;
if (o < 0) *--f = '-';
return std::string(f, (str + 16) - f);
}
}
namespace hopman_fast {
struct itostr_helper {
static unsigned out[10000];
itostr_helper() {
progress_timer t;
for (int i = 0; i < 10000; i++) {
unsigned v = i;
char * o = (char*)(out + i);
o[3] = v % 10 + '0';
o[2] = (v % 100) / 10 + '0';
o[1] = (v % 1000) / 100 + '0';
o[0] = (v % 10000) / 1000;
if (o[0]) o[0] |= 0x30;
else if (o[1] != '0') o[0] |= 0x20;
else if (o[2] != '0') o[0] |= 0x10;
else o[0] |= 0x00;
}
}
};
unsigned itostr_helper::out[10000];
itostr_helper hlp_init;
template <typename T>
std::string itostr(T o) {
typedef itostr_helper hlp;
unsigned blocks[3], *b = blocks + 2;
blocks[0] = o < 0 ? ~o + 1 : o;
blocks[2] = blocks[0] % 10000; blocks[0] /= 10000;
blocks[2] = hlp::out[blocks[2]];
if (blocks[0]) {
blocks[1] = blocks[0] % 10000; blocks[0] /= 10000;
blocks[1] = hlp::out[blocks[1]];
blocks[2] |= 0x30303030;
b--;
}
if (blocks[0]) {
blocks[0] = hlp::out[blocks[0] % 10000];
blocks[1] |= 0x30303030;
b--;
}
char* f = ((char*)b);
f += 3 - (*f >> 4);
char* str = (char*)blocks;
if (o < 0) *--f = '-';
return std::string(f, (str + 12) - f);
}
}
namespace voigt {
template<typename T>
struct assert_integral
{
enum { value = (T)0.5 };
char test[1 - 4 * value];
};
template<typename T, bool is_signed, size_t bits>
struct itostr_impl { };
template<typename T, bool is_signed>
struct itostr_impl<T,is_signed,8>
{
static std::string cvt(T val)
{
std::string retval(5, '\0');
int i = 0;
char ch = 0;
if (is_signed) {
if (val < 0) {
retval[i] = '-';
++i;
if (val <= -100) {
ch = '1';
val += 100;
}
val = -val;
}
else if (val >= 100) {
ch |= '1';
val -= 100;
}
}
else {
if (val >= 200) {
ch |= '2';
val -= 200;
}
else if (val >= 100) {
ch |= '1';
val -= 100;
}
}
if (ch) {
retval[i] = ch;
++i;
ch = '0';
}
if (val >= 80) {
ch |= '8';
val -= 80;
}
else if (val >= 40) {
ch |= '4';
val -= 40;
}
if (val >= 20) {
ch |= '2';
val -= 20;
}
if (val >= 10) {
ch |= '1';
val -= 10;
}
if (ch) {
retval[i] = ch;
++i;
}
retval[i] = '0' + val;
retval.resize(i+1);
return retval;
}
};
template<typename T, bool is_signed>
struct itostr_impl<T,is_signed,16>
{
static std::string cvt(T val)
{
std::string retval(7, '\0');
int i = 0;
char ch = 0;
if (is_signed) {
if (val < 0) {
retval[i] = '-';
++i;
if (val <= -20000) {
ch = '2';
val += 20000;
}
val = -val;
}
else if (val >= 20000) {
ch |= '2';
val -= 20000;
}
}
else {
if (val >= 40000) {
ch |= '4';
val -= 40000;
}
else if (val >= 20000) {
ch |= '2';
val -= 20000;
}
}
if (val >= 10000) {
ch |= '1';
val -= 10000;
}
if (ch) {
retval[i] = ch;
++i;
ch = '0';
}
if (val >= 8000) {
ch |= '8';
val -= 8000;
}
else if (val >= 4000) {
ch |= '4';
val -= 4000;
}
if (val >= 2000) {
ch |= '2';
val -= 2000;
}
if (val >= 1000) {
ch |= '1';
val -= 1000;
}
if (ch) {
retval[i] = ch;
++i;
ch = '0';
}
if (val >= 800) {
ch |= '8';
val -= 800;
}
else if (val >= 400) {
ch |= '4';
val -= 400;
}
if (val >= 200) {
ch |= '2';
val -= 200;
}
if (val >= 100) {
ch |= '1';
val -= 100;
}
if (ch) {
retval[i] = ch;
++i;
ch = '0';
}
if (val >= 80) {
ch |= '8';
val -= 80;
}
else if (val >= 40) {
ch |= '4';
val -= 40;
}
if (val >= 20) {
ch |= '2';
val -= 20;
}
if (val >= 10) {
ch |= '1';
val -= 10;
}
if (ch) {
retval[i] = ch;
++i;
}
retval[i] = '0' + val;
retval.resize(i+1);
return retval;
}
};
const char digit_pair_table[201] = {
"00010203040506070809"
"10111213141516171819"
"20212223242526272829"
"30313233343536373839"
"40414243444546474849"
"50515253545556575859"
"60616263646566676869"
"70717273747576777879"
"80818283848586878889"
"90919293949596979899"
};
template<typename T, bool is_signed>
struct itostr_impl<T,is_signed,32>
{
static std::string cvt(T val)
{
char buf[11], ch = 0;
char* start = buf + 1;
char* p = start;
bool neg = val < 0;
int digit;
if (is_signed) {
if (neg) {
if (val <= -2000000000) {
ch = '2';
val += 2000000000;
}
val = -val;
}
else if (val >= 2000000000) {
ch = '2';
val -= 2000000000;
}
}
else {
if (val >= 4000000000U) {
ch |= '4';
val -= 4000000000U;
}
else if (val >= 2000000000) {
ch |= '2';
val -= 2000000000;
}
}
if (val >= 1000000000) {
ch |= '1';
val -= 1000000000;
}
if (ch) {
*p = ch;
++p;
ch = '0';
}
else if (val < 1000) {
if (val < 10) goto d1;
if (val < 1000) goto d10;
}
else {
if (val < 100000) goto d1000;
if (val < 10000000) goto d100000;
}
#define DO_PAIR(n) \
d##n: \
digit = val / n; \
*(p++) = digit_pair_table[digit*2]; \
*(p++) = digit_pair_table[digit*2+1]; \
val -= n * digit;
DO_PAIR(10000000);
DO_PAIR(100000);
DO_PAIR(1000);
DO_PAIR(10);
d1:
*p = '0' | val;
if (p > start && *start == '0') ++start;
if (is_signed && neg) *--start = '-';
return std::string(start, p+1-start);
}
};
template<typename T>
std::string itostr(T val)
{
sizeof(assert_integral<T>);
return itostr_impl<T,((T)-1) < 0,sizeof(T) * CHAR_BIT>::cvt(val);
}
}
namespace ergosys {
typedef unsigned buf_t;
static buf_t * reduce(unsigned val, buf_t * stp) {
unsigned above = val / 10000;
if (above != 0) {
stp = reduce(above, stp);
val -= above * 10000;
}
buf_t digit = val / 1000;
*stp++ = digit + '0';
val -= digit * 1000;
digit = val / 100;
*stp++ = digit + '0';
val -= digit * 100;
digit = val / 10;
*stp++ = digit + '0';
val -= digit * 10;
*stp++ = val + '0';
return stp;
}
std::string itostr(int input) {
buf_t buf[16];
if(input == INT_MIN)
return std::string("-2147483648");
// handle negative
unsigned val = input;
if(input < 0)
val = -input;
buf[0] = '0';
buf_t* endp = reduce(val, buf+1);
*endp = 127;
buf_t * stp = buf+1;
while (*stp == '0')
stp++;
if (stp == endp)
stp--;
if (input < 0) {
stp--;
*stp = '-';
}
return std::string(stp, endp);
}
std::string itostr(unsigned input) {
buf_t buf[16];
unsigned val = input;
buf_t* endp = reduce(val, buf);
*endp = 127;
buf_t * stp = buf;
while (*stp == '0')
stp++;
if (stp == endp)
stp--;
return std::string(stp, endp);
}
}
namespace user {
const char digit_pairs[201] = {
"00010203040506070809"
"10111213141516171819"
"20212223242526272829"
"30313233343536373839"
"40414243444546474849"
"50515253545556575859"
"60616263646566676869"
"70717273747576777879"
"80818283848586878889"
"90919293949596979899"
};
std::string& itostr(int n, std::string& s)
{
if(n==0)
{
s="0";
return s;
}
int sign = -(n<0);
unsigned int val = (n^sign)-sign;
int size;
if(val>=10000)
{
if(val>=10000000)
{
if(val>=1000000000)
size=10;
else if(val>=100000000)
size=9;
else
size=8;
}
else
{
if(val>=1000000)
size=7;
else if(val>=100000)
size=6;
else
size=5;
}
}
else
{
if(val>=100)
{
if(val>=1000)
size=4;
else
size=3;
}
else
{
if(val>=10)
size=2;
else
size=1;
}
}
size -= sign;
s.resize(size);
char* c = &s[0];
if(sign)
*c='-';
c += size-1;
while(val>=100)
{
int pos = val % 100;
val /= 100;
*(short*)(c-1)=*(short*)(digit_pairs+2*pos);
c-=2;
}
while(val>0)
{
*c--='0' + (val % 10);
val /= 10;
}
return s;
}
std::string& itostr(unsigned val, std::string& s)
{
if(val==0)
{
s="0";
return s;
}
int size;
if(val>=10000)
{
if(val>=10000000)
{
if(val>=1000000000)
size=10;
else if(val>=100000000)
size=9;
else
size=8;
}
else
{
if(val>=1000000)
size=7;
else if(val>=100000)
size=6;
else
size=5;
}
}
else
{
if(val>=100)
{
if(val>=1000)
size=4;
else
size=3;
}
else
{
if(val>=10)
size=2;
else
size=1;
}
}
s.resize(size);
char* c = &s[size-1];
while(val>=100)
{
int pos = val % 100;
val /= 100;
*(short*)(c-1)=*(short*)(digit_pairs+2*pos);
c-=2;
}
while(val>0)
{
*c--='0' + (val % 10);
val /= 10;
}
return s;
}
template <typename T>
std::string itostr(T t) {
std::string ret;
itostr(t, ret);
return ret;
}
}
namespace timo {
const char digit_pairs[201] = {
"00010203040506070809"
"10111213141516171819"
"20212223242526272829"
"30313233343536373839"
"40414243444546474849"
"50515253545556575859"
"60616263646566676869"
"70717273747576777879"
"80818283848586878889"
"90919293949596979899"
};
static const int BUFFER_SIZE = 11;
std::string itostr(int val)
{
char buf[BUFFER_SIZE];
char *it = &buf[BUFFER_SIZE-2];
if(val>=0) {
int div = val/100;
while(div) {
memcpy(it,&digit_pairs[2*(val-div*100)],2);
val = div;
it-=2;
div = val/100;
}
memcpy(it,&digit_pairs[2*val],2);
if(val<10)
it++;
} else {
int div = val/100;
while(div) {
memcpy(it,&digit_pairs[-2*(val-div*100)],2);
val = div;
it-=2;
div = val/100;
}
memcpy(it,&digit_pairs[-2*val],2);
if(val<=-10)
it--;
*it = '-';
}
return std::string(it,&buf[BUFFER_SIZE]-it);
}
std::string itostr(unsigned int val)
{
char buf[BUFFER_SIZE];
char *it = (char*)&buf[BUFFER_SIZE-2];
int div = val/100;
while(div) {
memcpy(it,&digit_pairs[2*(val-div*100)],2);
val = div;
it-=2;
div = val/100;
}
memcpy(it,&digit_pairs[2*val],2);
if(val<10)
it++;
return std::string((char*)it,(char*)&buf[BUFFER_SIZE]-(char*)it);
}
}
#define TEST(x, n) \
stringstream ss; \
string s = n::itostr(x); \
ss << (long long)x; \
if (ss.str() != s) { \
passed = false; \
break; \
}
#define test(x) { \
passed = true; \
if (0 && passed) { \
char c = CHAR_MIN; \
do { \
TEST(c, x); \
} while (c++ != CHAR_MAX); \
if (!passed) cout << #x << " failed char!!!" << endl; \
/*if (passed) cout << #x << " passed char" << endl;*/ \
} \
if (0 && passed) { \
short c = numeric_limits<short>::min(); \
do { \
TEST(c, x); \
} while (c++ != numeric_limits<short>::max()); \
if (!passed) cout << #x << " failed short!!!" << endl; \
/*if (passed) cout << #x << " passed short" << endl;*/ \
} \
if (passed) { \
int c = numeric_limits<int>::min(); \
do { \
TEST(c, x); \
} while ((c += 100000) < numeric_limits<int>::max() - 100000); \
if (!passed) cout << #x << " failed int!!!" << endl; \
/*if (passed) cout << #x << " passed int" << endl; */\
} \
if (passed) { \
unsigned c = numeric_limits<unsigned>::max(); \
do { \
TEST(c, x); \
} while ((c -= 100000) > 100000); \
if (!passed) cout << #x << " failed unsigned int!!!" << endl; \
/*if (passed) cout << #x << " passed unsigned int" << endl;*/ \
} \
}
#define time(x) \
if (passed) { \
cout << #x << ": "; \
progress_timer t; \
unsigned s = 0; \
if (do_time) { \
for (int n = 0; n < N1; n++) { \
int i = 0; \
while (i < N2) { \
i += x::itostr(N2 - i).size() * mult; \
i += x::itostr(i - N2).size() * mult; \
} \
s += i / mult; \
} \
} \
k += s; \
cout << s / double(t.elapsed()) * CLOCKS_PER_SEC / 1000000 << " MB/sec --- "; \
}
int N1 = 1, N2 = 1000000000;
int mult = 1; // used to stay under timelimit on ideone
unsigned long long k = 0;
int main(int argc, char** argv) {
bool do_time = 1, do_test = 1;
cin >> mult;
bool passed = true;
{
if (do_test) test(hopman_fun);
if (do_time) time(hopman_fun);
}
{
if (do_test) test(hopman_fast);
if (do_time) time(hopman_fast);
}
{
if (do_test) test(voigt);
if (do_time) time(voigt);
}
{
if (do_test) test(user_voigt_timo);
if (do_time) time(user_voigt_timo);
}
{
if (do_test) test(timo);
if (do_time) time(timo);
}
{
if (do_test) test(user);
if (do_time) time(user);
}
{
if (do_test) test(ergosys);
if (do_time) time(ergosys);
}
return k;
}