#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/times.h>
static unsigned P[] = {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419,
421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503,
509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607,
613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
};
static int P_COUNT = sizeof(P)/sizeof(*P);
unsigned compute_fast (unsigned n, int I);
unsigned compute_slow (unsigned n, int I) {
unsigned sum = 1;
unsigned x = n;
for (int i = I; i < P_COUNT; ++i) {
if (P[i] > x / P[i]) break; /* remaining primes won't divide x */
if (x % P[i] == 0) { /* P[i] is a divisor of n */
unsigned sub = P[i] + 1; /* add in power of P[i] */
x /= P[i]; /* reduce x by P[i] */
while (x % P[i] == 0) { /* while P[i] still divides x */
x /= P[i]; /* reduce x */
sub = sub * P[i] + 1; /* add by another power of P[i] */
}
sum *= sub; /* product of sums */
return sum * compute_fast(x, i+1);
}
}
if (x > 1) sum *= x + 1; /* if x > 1, then x is prime */
return sum;
}
unsigned compute_fast (unsigned n, int I) {
static unsigned M[5000000 + 1]; /* memoization of results */
if (!M[n])
M[n] = compute_slow(n, I);
return M[n];
}
unsigned compute (unsigned n) {
return compute_fast(n, 0) - n;
}
int main () {
unsigned cases = 500000;
unsigned i;
unsigned *n;
unsigned *r;
struct tms beg;
struct tms end;
n
= malloc(cases
* sizeof(*n
)); for (i = 0; i < cases; ++i) {
n[i] = i + 1;
}
for (i = 0; i < cases; ++i) {
unsigned j
= rand() % 500000; unsigned x = n[i];
n[i] = n[j];
n[j] = x;
}
r
= malloc(cases
* sizeof(*r
)); times(&beg);
for (i = 0; i < cases; ++i) {
r[n[i]-1] = compute(n[i]);
}
times(&end);
double x = 0;
x += end.tms_utime;
x += end.tms_stime;
x -= beg.tms_utime;
x -= beg.tms_stime;
printf("%f seconds\n", x
/ sysconf
(_SC_CLK_TCK
)); return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHVuaXN0ZC5oPgojaW5jbHVkZSA8c3lzL3RpbWVzLmg+CiAKc3RhdGljIHVuc2lnbmVkIFBbXSA9IHsKMiwgMywgNSwgNywgMTEsIDEzLCAxNywgMTksIDIzLCAyOSwgMzEsIDM3LCA0MSwgNDMsIDQ3LCA1MywgNTksIDYxLCA2NywgNzEsCjczLCA3OSwgODMsIDg5LCA5NywgMTAxLCAxMDMsIDEwNywgMTA5LCAxMTMsIDEyNywgMTMxLCAxMzcsIDEzOSwgMTQ5LCAxNTEsCjE1NywgMTYzLCAxNjcsIDE3MywgMTc5LCAxODEsIDE5MSwgMTkzLCAxOTcsIDE5OSwgMjExLCAyMjMsIDIyNywgMjI5LCAyMzMsCjIzOSwgMjQxLCAyNTEsIDI1NywgMjYzLCAyNjksIDI3MSwgMjc3LCAyODEsIDI4MywgMjkzLCAzMDcsIDMxMSwgMzEzLCAzMTcsCjMzMSwgMzM3LCAzNDcsIDM0OSwgMzUzLCAzNTksIDM2NywgMzczLCAzNzksIDM4MywgMzg5LCAzOTcsIDQwMSwgNDA5LCA0MTksCjQyMSwgNDMxLCA0MzMsIDQzOSwgNDQzLCA0NDksIDQ1NywgNDYxLCA0NjMsIDQ2NywgNDc5LCA0ODcsIDQ5MSwgNDk5LCA1MDMsCjUwOSwgNTIxLCA1MjMsIDU0MSwgNTQ3LCA1NTcsIDU2MywgNTY5LCA1NzEsIDU3NywgNTg3LCA1OTMsIDU5OSwgNjAxLCA2MDcsCjYxMywgNjE3LCA2MTksIDYzMSwgNjQxLCA2NDMsIDY0NywgNjUzLCA2NTksIDY2MSwgNjczLCA2NzcsIDY4MywgNjkxLCA3MDEsCn07CiAKc3RhdGljIGludCBQX0NPVU5UID0gc2l6ZW9mKFApL3NpemVvZigqUCk7CiAKdW5zaWduZWQgY29tcHV0ZV9mYXN0ICh1bnNpZ25lZCBuLCBpbnQgSSk7CiAKdW5zaWduZWQgY29tcHV0ZV9zbG93ICh1bnNpZ25lZCBuLCBpbnQgSSkgewogICAgdW5zaWduZWQgc3VtID0gMTsKICAgIHVuc2lnbmVkIHggPSBuOwogICAgZm9yIChpbnQgaSA9IEk7IGkgPCBQX0NPVU5UOyArK2kpIHsKICAgICAgICBpZiAoUFtpXSA+IHggLyBQW2ldKSBicmVhazsgICAgLyogcmVtYWluaW5nIHByaW1lcyB3b24ndCBkaXZpZGUgeCAqLwogICAgICAgIGlmICh4ICUgUFtpXSA9PSAwKSB7ICAgICAgICAgICAvKiBQW2ldIGlzIGEgZGl2aXNvciBvZiBuICovCiAgICAgICAgICAgIHVuc2lnbmVkIHN1YiA9IFBbaV0gKyAxOyAgIC8qIGFkZCBpbiBwb3dlciBvZiBQW2ldICovCiAgICAgICAgICAgIHggLz0gUFtpXTsgICAgICAgICAgICAgICAgIC8qIHJlZHVjZSB4IGJ5IFBbaV0gKi8KICAgICAgICAgICAgd2hpbGUgKHggJSBQW2ldID09IDApIHsgICAgLyogd2hpbGUgUFtpXSBzdGlsbCBkaXZpZGVzIHggKi8KICAgICAgICAgICAgICAgIHggLz0gUFtpXTsgICAgICAgICAgICAgLyogcmVkdWNlIHggKi8KICAgICAgICAgICAgICAgIHN1YiA9IHN1YiAqIFBbaV0gKyAxOyAgLyogYWRkIGJ5IGFub3RoZXIgcG93ZXIgb2YgUFtpXSAqLwogICAgICAgICAgICB9CiAgICAgICAgICAgIHN1bSAqPSBzdWI7ICAgICAgICAgICAgICAgIC8qIHByb2R1Y3Qgb2Ygc3VtcyAqLwogICAgICAgICAgICByZXR1cm4gc3VtICogY29tcHV0ZV9mYXN0KHgsIGkrMSk7CiAgICAgICAgfQogICAgfQogICAgaWYgKHggPiAxKSBzdW0gKj0geCArIDE7ICAgICAgICAgICAvKiBpZiB4ID4gMSwgdGhlbiB4IGlzIHByaW1lICovCiAgICByZXR1cm4gc3VtOwp9CiAKdW5zaWduZWQgY29tcHV0ZV9mYXN0ICh1bnNpZ25lZCBuLCBpbnQgSSkgewogICAgc3RhdGljIHVuc2lnbmVkIE1bNTAwMDAwMCArIDFdOyAgICAvKiBtZW1vaXphdGlvbiBvZiByZXN1bHRzICovCiAgICBpZiAoIU1bbl0pCiAgICAgICAgTVtuXSA9IGNvbXB1dGVfc2xvdyhuLCBJKTsKICAgIHJldHVybiBNW25dOwp9CiAKdW5zaWduZWQgY29tcHV0ZSAodW5zaWduZWQgbikgewogICAgcmV0dXJuIGNvbXB1dGVfZmFzdChuLCAwKSAtIG47Cn0KIAppbnQgbWFpbiAoKSB7CiAgICB1bnNpZ25lZCBjYXNlcyA9IDUwMDAwMDsKICAgIHVuc2lnbmVkIGk7CiAgICB1bnNpZ25lZCAqbjsKICAgIHVuc2lnbmVkICpyOwogICAgc3RydWN0IHRtcyBiZWc7CiAgICBzdHJ1Y3QgdG1zIGVuZDsKIAogICAgbiA9IG1hbGxvYyhjYXNlcyAqIHNpemVvZigqbikpOwogICAgZm9yIChpID0gMDsgaSA8IGNhc2VzOyArK2kpIHsKICAgICAgICBuW2ldID0gaSArIDE7CiAgICB9CiAgICBzcmFuZCgxMDEwMTAxKTsKICAgIGZvciAoaSA9IDA7IGkgPCBjYXNlczsgKytpKSB7CiAgICAgICAgdW5zaWduZWQgaiA9IHJhbmQoKSAlIDUwMDAwMDsKICAgICAgICB1bnNpZ25lZCB4ID0gbltpXTsKICAgICAgICBuW2ldID0gbltqXTsKICAgICAgICBuW2pdID0geDsKICAgIH0KICAgIHIgPSBtYWxsb2MoY2FzZXMgKiBzaXplb2YoKnIpKTsKICAgIHRpbWVzKCZiZWcpOwogICAgZm9yIChpID0gMDsgaSA8IGNhc2VzOyArK2kpIHsKICAgICAgICByW25baV0tMV0gPSBjb21wdXRlKG5baV0pOwogICAgfQogICAgdGltZXMoJmVuZCk7CiAgICBmcmVlKHIpOwogICAgZnJlZShuKTsKICAgIGRvdWJsZSB4ID0gMDsKICAgIHggKz0gZW5kLnRtc191dGltZTsKICAgIHggKz0gZW5kLnRtc19zdGltZTsKICAgIHggLT0gYmVnLnRtc191dGltZTsKICAgIHggLT0gYmVnLnRtc19zdGltZTsKICAgIHByaW50ZigiJWYgc2Vjb25kc1xuIiwgeCAvIHN5c2NvbmYoX1NDX0NMS19UQ0spKTsKICAgIHJldHVybiAwOwp9