def compute(f): prob = 0 loss = 1.-f win = 1.+2*f for i in xrange(0,1001): if loss**i * win ** (1000-i) >= 10**9: prob += ncr(1000,i) return prob
newDigDict[(tuple(newArray), newNumDigSatisfy, newArraySum)] = digDict[key] # setup memoization to be faster later if (tuple(newArray), newNumDigSatisfy, newArraySum) in newLocToOldLoc: newLocToOldLoc[(tuple(newArray), newNumDigSatisfy, newArraySum)] += [key] else: newLocToOldLoc[(tuple(newArray), newNumDigSatisfy, newArraySum)] = [key] solutions.append(currentSum) currentSum = 0 for digit in xrange(2, len(solutions)): currentSum += ncr(numDig, digit) * solutions[digit] % MOD #print numDig, "digit:", digit, "multiplier:", ncr(numDig, digit), "\tnumSol for", digit, ':', solutions[digit], "\ttotal count:", ncr(numDig, digit) * solutions[digit] print numDig, currentSum % MOD, ' \t', len( newDigDict), '\t', "Time Taken:", time.time() - START # bigger chunk of the problem. Making some small tracking changes can give us a speedup of up to 14x ...which is still not enough for 10^18 LOL for numDig in xrange(SEED_SIZE, SIZE): digDict = newDigDict newDigDict = dict() START = time.time() answerSums = 0 # slowest part of the code atm is this for loop... for newLoc in newLocToOldLoc.keys(): newDigDict[newLoc] = sum( [digDict[oldLoc] for oldLoc in newLocToOldLoc[newLoc]])
def dFast(p, k): sumz = 0 for m in xrange(k + 1, p - 1): sumz += ncr(m - 1, k) * multInverse(m, p) % p return sumz % p
currentSum += digDict[key] if (tuple(newArray), newNumDigSatisfy, newArraySum) in newDigDict: newDigDict[(tuple(newArray), newNumDigSatisfy, newArraySum)] += digDict[key] else: newDigDict[(tuple(newArray), newNumDigSatisfy, newArraySum)] = digDict[key] # setup memoization to be faster later if (tuple(newArray), newNumDigSatisfy, newArraySum) in newLocToOldLoc: newLocToOldLoc[(tuple(newArray), newNumDigSatisfy, newArraySum)] += [key] else: newLocToOldLoc[(tuple(newArray), newNumDigSatisfy, newArraySum)] = [ key ] solutions.append(currentSum) currentSum = 0 for digit in xrange(2,len(solutions)): currentSum += ncr(numDig, digit) * solutions[digit] % MOD #print numDig, "digit:", digit, "multiplier:", ncr(numDig, digit), "\tnumSol for", digit, ':', solutions[digit], "\ttotal count:", ncr(numDig, digit) * solutions[digit] print numDig, currentSum % MOD, ' \t', len(newDigDict), '\t', "Time Taken:", time.time() - START # bigger chunk of the problem. Making some small tracking changes can give us a speedup of up to 14x ...which is still not enough for 10^18 LOL for numDig in xrange(SEED_SIZE, SIZE): digDict = newDigDict newDigDict = dict() START = time.time() answerSums = 0 # slowest part of the code atm is this for loop... for newLoc in newLocToOldLoc.keys(): newDigDict[newLoc] = sum([digDict[oldLoc] for oldLoc in newLocToOldLoc[newLoc]]) for key in newDigDict.keys():
#NOTE TODO need to solve it import time, math from primes import ncr START = time.time() N = 10**9 K = 3 sumz = 0 k = ncr(N + K, K) for i in xrange(N): k = k * (N - i) / (N + K - i) sumz += k * 1.0 / (i + 1) if i % 10**4 == 0: print i + 1, k, k * 1.0 / (i + 1) print sumz print "Time Taken:", time.time() - START """ Notes! -At each step, if you do not take someone else's ticket, you can only do worse from what you're at. -Suppose that you could improve by getting ticket 'k'. The other person would only switch tickets with you if you have the highest ticket shown at the moment. Therefore, it is not beneficial for you to take anyone else's ticket. And the problem is, if you scratch your ticket, it WILL be taken away if it is better than your previous one (if you're last person with an unscratched ticket, person giving you it knows that it isn't better than what you currently have), or is worse than what you have in hand.
#NOTE TODO need to solve it import time, math from primes import ncr START = time.time() N = 10**9 K = 3 sumz = 0 k = ncr(N + K, K) for i in xrange( N ): k = k * (N - i) / (N + K - i) sumz += k * 1.0 / (i + 1) if i % 10**4 == 0: print i+1, k, k * 1.0 / (i + 1) print sumz print "Time Taken:", time.time() - START """ Notes! -At each step, if you do not take someone else's ticket, you can only do worse from what you're at. -Suppose that you could improve by getting ticket 'k'. The other person would only switch tickets with you if you have the highest ticket shown at the moment. Therefore, it is not beneficial for you to take anyone else's ticket. And the problem is, if you scratch your ticket, it WILL be taken away if it is better than your previous one (if you're last person with an unscratched ticket, person giving you it knows that it isn't better than what you currently have),
def gameB(n): return sum([(1.0) / (ncr(n, k) * k) for k in xrange(1, n + 1)])
def gameA(n): return sum([(1.0 * ncr(n, k)) / k for k in xrange(1, n + 1)]) / 2**n
def cat(n): return ncr(2*n,n)/(n+1)
import time START = time.time() from primes import ncr def cat(n): return ncr(2*n,n)/(n+1) SIZE = 12 count = 0 for i in xrange(1,SIZE//2+1): a = ncr(SIZE,i)* ncr(SIZE-i,i)/2 b = ncr(2*i,i)/2 c = b - cat(i) d = a * c / b count +=d print "Answer is:", count print "Time taken:", time.time() - START """ Congratulations, the answer you gave to problem 106 is correct. You are the 2840th person to have solved this problem. 10:36 ~/Desktop/python_projects/proj_euler $ python prob106.py Answer is: 21384 Time taken: 0.0530858039856 So the interesting thing for this problem is, we only need to care about pairs that have an equal number of items. In other words, we only need to care about comparisons between subsets of the same size. This means that first off, we can throw away all comparisons between sets of different sizes (like size 1 vs size 3). Next, if we think about it, we don't need to compare two sets {a,b} and {c,d} if a < b < c < d. We already know that a < c and b < d, which means their sum is going to be different. The interesting thing is, you can see this as wanting sets that DO NOT satisfy the parenthesis matching problem (where you have n sets of '(' and ')' and you want to count how many possible combinations of ( and ) can be made so that they're matched correctly.
def cat(n): return ncr(2 * n, n) / (n + 1)
import time START = time.time() from primes import ncr def cat(n): return ncr(2 * n, n) / (n + 1) SIZE = 12 count = 0 for i in xrange(1, SIZE // 2 + 1): a = ncr(SIZE, i) * ncr(SIZE - i, i) / 2 b = ncr(2 * i, i) / 2 c = b - cat(i) d = a * c / b count += d print "Answer is:", count print "Time taken:", time.time() - START """ Congratulations, the answer you gave to problem 106 is correct. You are the 2840th person to have solved this problem. 10:36 ~/Desktop/python_projects/proj_euler $ python prob106.py Answer is: 21384 Time taken: 0.0530858039856 So the interesting thing for this problem is, we only need to care about pairs that have an equal number of items. In other words, we only need to care about comparisons between subsets of the same size. This means that first off, we can throw away all comparisons between sets of different sizes (like size 1 vs size 3).
def dFast(p, k): sumz = 0 for m in xrange(k+1, p-1): sumz += ncr(m-1, k) * multInverse(m, p) % p return sumz % p