先介绍一下,ProjectEuler,欧拉工程,是一个国外的练习数论的网站,总共300多道题目。
网址是http://projecteuler.net/problems,有个特点是可以使用任何编程语言,或者自己手算,得到答案提交就可以了。
这个和OJ是不一样的。提交通过以后,可以去论坛看看那别人的解决方法,以及参与讨论。
好久没有动手做题了,那天看到论坛又有人在说,就来做做。我使用的语言是python,Life is short,you need Python
前面的题目很基础,但是刷水体不是我的风格,所以我尽量用高效的,不一样的的方法来解决。
1
|
Add all the natural numbers below one thousand that are multiples of 3 or 5. |
没什么特别的,用容斥就可以了
def main(): MAX = 999 print 3 * (MAX/3)*(MAX/3+1) /2 + 5 * (MAX/5)*(MAX/5+1) /2 - 15 * (MAX/15)*(MAX/15+1) /2 if __name__ == '__main__': main()
2
|
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms. |
这一题是寻找一个小于4000000的最大的那个fibonacci数,
答案很小,朴素方法几行就写完了,但是我还是选择用高级方法
我们可以用矩阵快速幂乘来以O(logN)的时间获得第N个fibonacci数,然后我们选定范围二分答案就可以了
#|Fn+1| = |1 1| * |Fn | #|Fn | |1 0| |Fn-1| # #|Fn+1| = (|1 1|)**n * |F1| #|Fn | (|1 0|) |F0| class matrix: def __init__(self,data): self.data = data def multiple(self, m2): N = len(self.data) if isinstance(m2,matrix): m2 = m2.data new = [] for i in range(N): new.append([0]*N) for i in range(N): for j in range(N): for k in range(N): new[i][j] += self.data[i][k]*m2[k][j] return matrix(new) def __str__(self): return str(self.data) def __repr__(self): return str(self.data) class Fibonacci(): def __init__(self,N): fac = matrix([[1,1],[1,0]]) self.base = [] for i in range (N-1): self.base.append(fac) fac = fac.multiple(fac) def get(self,N): i = 0 a = matrix([[1,0],[0,1]]) while N > 0: if N&1 > 0: a = a.multiple(self.base[i]) N >>= 1 i+=1 return a.data[1][0]+a.data[1][1] def bs_ans(low, high,limit): f = Fibonacci(10) ans = 0 ans_p = 0 while low <= high: v = f.get((low+high)>>1) if v > limit: high = (low+high)/2-1 else: ans = v ans_p = (low+high)/2 low = (low+high)/2 + 1 return ans_p,ans def main(): p,limit = bs_ans(1,50,4000000) while True: if (p + 1) % 3 == 0: break p -= 1 f = Fibonacci(10) print (f.get(p+2)-1)/2 if __name__ == '__main__': main()
3
|
Find the largest prime factor of a composite number. |
寻找一个数的最大的质因子,直接分解质因数就可以了。数量比较小,用的最基础的分解质因数的方法,有兴趣的同学可以看看
import math def PrimeList(N = None,limit = None): if N ==None and limit ==None: raise Exception('need either N or limit') ans = [2,3] i = 5 dt = 2 while True: if N != None and len(ans) >= N : break if limit != None and ans[-1] >= limit: break f = True for j in ans: if i%j == 0: f = False break if f: ans.append(i) i += dt dt = 6 - dt return ans def IntegerFactorization(N): pass def main(): N = 600851475143 a = math.sqrt(N) print a plist = PrimeList(limit=a)[::-1] for p in plist: if N % p == 0: print p break if __name__ == '__main__': main()
4
|
Find the largest palindrome made from the product of two 3-digit numbers. |
没想到什么好方法,暴力的
def main(): ans = 0 for i in xrange(100,1000): for j in xrange(100,1000): v = i * j d = str(v) e=d[::-1] if d == e: if v > ans: ans = v print ans if __name__ == '__main__': main()
5
|
What is the smallest number divisible by each of the numbers 1 to 20? |
典型的最小公倍数,N个数的最小公倍数,等于LCM(A1,LCM(A2,A3,...An-1))
def GCD(L): if len(L) > 2: return GCD([L[0], GCD(L[1:])]) a = max(L) b = min(L) while a % b != 0: t = b b = a % b a = t return b def LCM(L): if len(L) > 2: return LCM([L[0],LCM(L[1:])]) return L[0] * L[1] / GCD(L) print GCD(range(1,21)) print LCM(range(1,21))
6
|
What is the difference between the sum of the squares and the square of the sums? |
好吧大整数的题目(python完全没有感觉...),暴力的
print sum(range(101))**2 - sum([x**2 for x in range(101)])
7
|
Find the 10001st prime. |
找第几个质数,因为数量稍大了,所以用了填充法筛质数,比较常用的方法
def PrimeList(N = None,limit = None): if N ==None and limit ==None: raise Exception('need either N or limit') ans = [2,3] i = 5 dt = 2 while True: if N != None and len(ans) >= N : break if limit != None and ans[-1] >= limit: break f = True for j in ans: if i%j == 0: f = False break if f: ans.append(i) i += dt dt = 6 - dt return ans def IntegerFactorization(N): pass print PrimeList(10001)[-1]
8
|
Discover the largest product of five consecutive digits in the 1000-digit number. |
这题可以注意到如果序列中有0,就全为0了。所以我们可以用0,分割序列,然后每个序列如果长度少于5 就可以直接skip
剩下的每个子序列单独暴力就ok了。
def calc(L,N): m = 0 for i in xrange(len(L)-N+1): ans = reduce(lambda m,n:m*n,L[i:i+N]) if ans >m: m = ans return m def main(): s = ''' 73167176531330624919225119674426574742355349194934 96983520312774506326239578318016984801869478851843 85861560789112949495459501737958331952853208805511 12540698747158523863050715693290963295227443043557 66896648950445244523161731856403098711121722383113 62229893423380308135336276614282806444486645238749 30358907296290491560440772390713810515859307960866 70172427121883998797908792274921901699720888093776 65727333001053367881220235421809751254540594752243 52584907711670556013604839586446706324415722155397 53697817977846174064955149290862569321978468622482 83972241375657056057490261407972968652414535100474 82166370484403199890008895243450658541227588666881 16427171479924442928230863465674813919123162824586 17866458359124566529476545682848912883142607690042 24219022671055626321111109370544217506941658960408 07198403850962455444362981230987879927244284909188 84580156166097919133875499200524063689912560717606 05886116467109405077541002256983155200055935729725 71636269561882670428252483600823257530420752963450 ''' s = [map(int,list(s)) for s in [subs for subs in ''.join(s.split()).split('0') if len(subs) > 4]] ans = 0 for l in s: r = calc(l,5) if r > ans: ans = r print ans if __name__ == '__main__': main()
9
|
Find the only Pythagorean triplet, {a, b, c}, for which a + b + c = 1000. |
算了半天,还是暴力的
def main(): for a in xrange(1,1001): b = a while a*a + b*b <= (1000-a-b)**2: if a*a + b*b == (1000-a-b)**2: print a,b,1000-a-b print a*b*(1000-a-b) b += 1 if __name__ == '__main__': main()
10
|
Calculate the sum of all the primes below two million. |
import math def PrimeList(N = None,limit = None): ''' return first N primes or primes <= limit ''' if N ==None and limit ==None: raise Exception('need either N or limit') ans = [2,3] i = 5 dt = 2 while True: if N != None and len(ans) >= N : break if limit != None and ans[-1] >= limit: break f = True for j in ans: if i%j == 0: f = False break if f: ans.append(i) i += dt dt = 6 - dt return ans def PrimeListFill(limit): ''' return primes <= limit ''' A = [True] * (limit + 1) plist = PrimeList(limit=int(math.sqrt(limit))) for p in plist: n = 2 * p while n <= limit: A[n] = False n += p ans = [] for i in xrange(2,len(A)): if A[i]: ans.append(i) return ans def main(): L = PrimeListFill(2000000) print sum(L) if __name__ == '__main__': main()