To reduce the number of iterations, you can increase the trial product by 1, instead of increasing the trial factor by 1. Then you check if the trial product is divided by the argument f (). This will allow you to quickly move to larger values, since you can skip the numeric values โโ4 through 9 in the product when adding 1.
Below, the C code ends in less than 5 minutes on a 2.4 GHz PC:
#include <stdio.h> #include <string.h> #include <assert.h> #include <stddef.h> #include <time.h> typedef unsigned uint; typedef unsigned char uint8; typedef unsigned long long uint64; uint64 f(uint n, uint64* multiplier) { uint8 carry, digits[20]; // 20 digits max for 64-bit values uint digcnt = 1, i; uint64 result; assert(n > 0); #if 0 // short cut: // // f(9) = 12222 = 9 * 1358 // f(99) = 1122222222 = 99 * 11335578 // f(999) = 111222222222222 = 999 * 111333555778 // f(9999) = 11112222222222222222 = 9999 * 1111333355557778 if (n == 9999) { *multiplier = 11112222222222222222ULL / 9999; return 11112222222222222222ULL; } #endif memset(digits, 0, sizeof(digits)); for (;;) { carry = 1; for (i = 0; carry; i++) { assert(i < sizeof(digits)); carry += digits[i]; digits[i] = carry % 3; carry /= 3; } if (i >= digcnt) digcnt = i; result = 0; for (i = 0; i < digcnt; i++) result = result * 10 + digits[digcnt - 1 - i]; if (result % n == 0) { *multiplier = result / n; break; } } return result; } int main(void) { uint i; uint64 sum = 0, product, multiplier; time_t t; char* p; for (i = 1; i <= 10000; i++) { product = f(i, &multiplier); printf("%s ", ((time(&t), p = ctime(&t)), p[strlen(p) - 1] = '\0', p)); printf("f(%u) = %llu = %u * %llu\n", i, product, i, multiplier); sum += multiplier; } printf("%s ", ((time(&t), p = ctime(&t)), p[strlen(p) - 1] = '\0', p)); printf("sum(f(n)/n) = %llu\n", sum); return 0; }
Output:
Mon Jan 9 12:18:22 2012 f(1) = 1 = 1 * 1 Mon Jan 9 12:18:22 2012 f(2) = 2 = 2 * 1 Mon Jan 9 12:18:22 2012 f(3) = 12 = 3 * 4 Mon Jan 9 12:18:22 2012 f(4) = 12 = 4 * 3 Mon Jan 9 12:18:22 2012 f(5) = 10 = 5 * 2 Mon Jan 9 12:18:22 2012 f(6) = 12 = 6 * 2 Mon Jan 9 12:18:22 2012 f(7) = 21 = 7 * 3 Mon Jan 9 12:18:22 2012 f(8) = 112 = 8 * 14 Mon Jan 9 12:18:22 2012 f(9) = 12222 = 9 * 1358 ... Mon Jan 9 12:18:39 2012 f(9998) = 111122211112 = 9998 * 11114444 Mon Jan 9 12:22:50 2012 f(9999) = 11112222222222222222 = 9999 * 1111333355557778 Mon Jan 9 12:22:50 2012 f(10000) = 10000 = 10000 * 1 Mon Jan 9 12:22:50 2012 sum(f(n)/n) = 1111981904675169
If you change #if 0 to #if 1 and turn on the short cut mentioned in Peter Laurie's comment, it will end in about 1 minute.
source share