def non_coprime_sum_pattern(m, x_max, k_max=4): '''Run this once to get an idea of what the sum of Fnx is for a non-co-prime factor m of 15! for n=10^k, k=0,1,2,3,... .''' for n in 10 ** np.arange(k_max): fnx_bf = Fnx_bf(n, m, x_max) s_bf = sum_mod(fnx_bf, m) print 'n %6d s %5d' % (n, s_bf), 'BF fnx', fnx_bf # Turn on debugging printouts to observe pattern return s_bf, m # Assuming constant s_bf for large k
F = Fib(r=m) f = np.array([F(i) for i in xrange(n + 1)]) return map(long, (polyval_mod(f, x, m) for x in xrange(x_max + 1))) def non_coprime_sum_pattern(m, x_max, k_max=4): '''Run this once to get an idea of what the sum of Fnx is for a non-co-prime factor m of 15! for n=10^k, k=0,1,2,3,... .''' for n in 10 ** np.arange(k_max): fnx_bf = Fnx_bf(n, m, x_max) s_bf = sum_mod(fnx_bf, m) print 'n %6d s %5d' % (n, s_bf), 'BF fnx', fnx_bf # Turn on debugging printouts to observe pattern return s_bf, m # Assuming constant s_bf for large k def crt(a): '''Returns the basic solution to the system x = a[i][0] (mod a[i][1]), i=0..len(a)-1 using the Chinese Remainder Theorem. All a[i][1] must be co-prime (although a weaker condition involving the a[i][0]''s is also sufficient for a solution, this implementation is not guaranteed to work for it).''' a, n = zip(*a) N = np.prod(map(long, n)) return sum(a[i] * (N / n[i]) * inv_mod(N / n[i], n[i]) for i in xrange(len(a))) % N '''Decompose 15! into factors with co-prime denominators (using division of Fn terms) and factors with non-co-prime denominators (using patterns observed for n=10^k) Solve for sum modulo 15! using the Chinese remainder theorem.''' sum_fnx_mod_fifteen_factorial = lambda n, x_max: crt([(sum_mod((Fnx(n, m, x) for x in xrange(x_max + 1)), m), m) for m in [2 ** 11, 3 ** 6, 7 ** 2, 13]] + [non_coprime_sum_pattern(m, x_max) for m in [5 ** 3, 11]]) if __name__ == "__main__": n = 10 ** 15 print sum_fnx_mod_fifteen_factorial(10 ** 15, 100)