def pe202(): """ | \| \| \| \| \| \| Expand triangle mirrors infinitely, then every +--+--+--+--+--+--+- possible path is a C-C line from bottomleft to C|\B|\A|\C|\B|\A|\C|\ somewhere upright and doesn't cross any vertex. | \| \| \| \| \| \| +--+--+--+--+--+--+- From the table can easity see that C-C lines are B|\A|\C|\B|\A|\C|\B|\ symmetric and lie on y = x + 3k. Without loss of | \| \| \| \| \| \| generality, we just need to count all (a, b) with +--+--+--+--+--+--+- a > b. A|\C|\B|\A|\C|\B|\A|\ | \| \| \| \| \| \| Also, from (0, 0) to (a, b), the amount of cross +--+--+--+--+--+--+- points with horizontal, vertical and diagonal C B A C B A C lines is (a-1) + (b-1) + (a+b-1) = 2a + 2b - 3. Therefore to bounce N times, we need to find all (a, b) that: (1) a + b = (N + 3) / 2 (2) gcd(a, b) = 1 (3) a - b = 3k Recording to reference articles PE202, the number of solutions of (1), (2) and (3) is: sum m(d) * f(n/d) for all d satisfying d|n where m(x) if mobius function, f(x) = floor(x/2) - floor(x/3) """ def f(x): return x / 2 - x / 3 N = 12017639147 N = (N + 3) / 2 # 6008819575 # 6008819575 = 5*5 * 11 * 17 * 23 * 29 * 41 * 47 pfactors = (5, 11, 17, 23, 29, 41, 47) count = f(N) for i in range(1, len(pfactors)+1): for pcomb in pec.combinations(pfactors, i): d = pef.cprod(pcomb) if i % 2: count -= f(N / d) else: count += f(N / d) # answer: 1209002624 return count * 2
def pe184(r=105): """ Find all points in first quardrant, then group them by slope (a.k.a. lines). Count how many points between each line and y-axis. There 5 different types of triangles. Count them out. """ from fractions import gcd def count(p, r): xp, yp = p xmax = int(math.sqrt(1. * r*r / (xp*xp + yp*yp)) * xp) yk = 1. * yp * xmax / xp if xmax*xmax + yk*yk < r*r: xmax += 1 c = 0 for x in range(1, xmax): ymax = int(math.sqrt(r*r - x*x)) if x*x + ymax*ymax == r*r: ymax -= 1 ymin = int(1. * x * yp / xp) + 1 c += ymax - ymin + 1 return c nq1, nline = 0, {} for x in range(1, r): for y in range(1, int(math.sqrt(r*r - x*x)) + 1): if x*x + y*y < r*r: nq1 += 1 g = gcd(x, y) xr = x / g yr = y / g if (xr, yr) in nline: nline[(xr, yr)] += 1 else: nline[(xr, yr)] = 1 # a(*4): one apex on y+, one apex on x+ # b(*8): one apex on y+, one apex in 1st quardrant # c(*4): one apex on y+, one apex in 2nd quardrant, one apex in 3rd quardrant # d(*4): two apexes in first quardrant # e(*2): three apexes in different quardrants a = (r-1) * (r-1) * nq1 b = c = d = e = 0 nty, ntx = {}, {} for (x, y), n in nline.iteritems(): nty[(x, y)] = count((x, y), r) ntx[(x, y)] = nq1 - n - nty[(x, y)] b += (r-1) * n * nty[(x, y)] c += (r-1) * n * nq1 e += 2 * n * n * ntx[(x, y)] for (x1, y1), (x2, y2) in pec.combinations(nline.keys(), 2): if 1.*y2/x2 > 1.*y1/x1: x1, y1, x2, y2 = x2, y2, x1, y1 coeff = nline[(x1, y1)] * nline[(x2, y2)] n = nty[(x2, y2)] - nty[(x1, y1)] - nline[(x1, y1)] d += coeff * n e += 2 * coeff * (n + nline[(x2, y2)] + 2 * ntx[(x2, y2)]) # answer: 1725323624056 return a*4 + b*8 + c*4 + d*4 + e*2