ProjectEuler,1-10题

先介绍一下,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.
又是质数打表,直接copy代码ok

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()


你可能感兴趣的:(ProjectEuler,1-10题)