Project Euler解题汇总 051 ~ 060 博客分类: 数学&编程 PHPScala.netCC++
程序员文章站
2024-02-16 15:41:28
...
注:本文代码中会使用按字典顺序生成所有的排列与筛法求素数中介绍的函数。
问题51:Find the smallest prime which, by changing the same part of the number, can form eight different primes.
题目简介:对于数字56**3(其中*表示占位符),将其中的两个*换成0~9中的数字,产生的10个数字中为素数的有:56003, 56113, 56333, 56443, 56663, 56773, 56993。56003是这一系列素数中最小的那个。
现在要求满足下列条件最小的那个素数:该数是由将某个数中的几位(不一定相邻)替换为相同数字而产生的8个素数中的一个。(注意:如果被替换的位置中有首位,则不能用0来替换)
答 案:121313
问题52:Find the smallest positive integer, x, such that 2x, 3x, 4x, 5x, and 6x, contain the same digits in some order.
题目简介:求最小的x,使得x的2倍,3倍,4倍,5倍,6倍都是由相同的数字组成
答 案:142857
PS:对1/7的循环节印象比较深刻,直接就写出来了,果然是对的:-)
问题53:How many values of C(n,r), for 1 ≤ n ≤ 100, exceed one-million?
题目简介:求组合数C(n,r) (1 ≤ n ≤ 100)中超过1000000的有多少个。
答 案:4075
问题54:How many hands did player one win in the game of poker?
题目简介:一个扑克牌游戏,判断提供的数据中玩家1赢的盘数有多少次
答 案:376
问题55:
How many Lychrel numbers are there below ten-thousand?
题目简介:首先介绍一个数学名词:利克瑞尔数(Lychrel Number):指的是将该数与将该数各数位逆序翻转后形成的新数相加、并将此过程反复迭代后,结果永远无法是一个回文数的自然数。
现在已知对于10000以内的自然数,要么能够在50步(指将这个数与其逆序后的数相加的过程)内得到一个回文数;要么该数是一个利克瑞尔数。
求:10000以内利克瑞尔数的个数
答 案:249
问题56:Considering natural numbers of the form, a^b, finding the maximum digital sum.
题目简介:记f(x)表示自然数x的各位数字之和,a^b表示a的b次方。对1≤a,b <100,求f(a^b)的最大值。
答 案:972
问题57:Investigate the expansion of the continued fraction for the square root of two.
题目简介:2的平方根有连分数的表示:√2 = 1 + 1/(2 + 1/(2 + 1/(2 + ... ))) = 1.414213...
展开其中的前四项为:
1 + 1/2 = 3/2 = 1.5
1 + 1/(2 + 1/2) = 7/5 = 1.4
1 + 1/(2 + 1/(2 + 1/2)) = 17/12 = 1.41666...
1 + 1/(2 + 1/(2 + 1/(2 + 1/2))) = 41/29 = 1.41379...
接下来的三项依次为:99/70, 239/169,577/408
而第八项是1393/985,注意,这是第一个出现分子位数超过分母位数的项(分子是4位数,而分母是3位数)
现在要求前1000项中,分子位数比分母位数多的个数。
答 案:153
问题58:
Investigate the number of primes that lie on the diagonals of the spiral grid.
题目简介:将自然数按如下方式逆时针排列:
37 36 35 34 33 32 31
38 17 16 15 14 13 30
39 18 05 04 03 12 29
40 19 06 01 02 11 28
41 20 07 08 09 10 27
42 21 22 23 24 25 26
43 44 45 46 47 48 49
其中标红色的表示出现在对角线上且为素数的自然数,注意对角线上一共有13个自然数,其中8个为素数。也就是说素数所占的比例为 8/13 ≈ 62%.
将上述方阵继续排列下去,求使得对角线上素数比例小于10%的方阵的最小边长。
答 案:26241
问题59:
Using a brute force attack, can you decrypt the cipher using XOR encryption?
题目简介:使用暴力破解一段使用异或方式加密的英文文本。
答 案:107359
问题60:Find a set of five primes for which any two primes concatenate to produce another prime.
题目简介:自然数3, 7, 109, 673有着非常奇特的性质:
1.它们都是素数
2.它们任意两个连接而成的数也是素数。比如7与3相连得到73是素数
3.它们是满足上面两个性质并且使得和最小的一组数
现在要求5个素数使得其中任意两个连接得到的数也是素数,并且使这5个数之和最小。
输出这5个数之和
答 案:26033
问题51:Find the smallest prime which, by changing the same part of the number, can form eight different primes.
题目简介:对于数字56**3(其中*表示占位符),将其中的两个*换成0~9中的数字,产生的10个数字中为素数的有:56003, 56113, 56333, 56443, 56663, 56773, 56993。56003是这一系列素数中最小的那个。
现在要求满足下列条件最小的那个素数:该数是由将某个数中的几位(不一定相邻)替换为相同数字而产生的8个素数中的一个。(注意:如果被替换的位置中有首位,则不能用0来替换)
答 案:121313
import java.util.Arrays.fill import eastsun.math.Util._ object Euler051 extends Application { var pa = getPrimes(1000000).filter{ _ > 100000 } var bf = new Array[Int](64) var res = 0 var i = 0 while(res == 0 && i < pa.length){ fill(bf,1) var j = i + 1 while(res == 0 && j < pa.length){ var pi = pa(i) var pj = pa(j) var id = 0 var tg = true var pie = -1 var pje = -1 do{ id = id<<1 if(pi%10 == pj%10) id = id|1 else if(pie != -1 && (pj%10 != pje || pi%10 != pie)) tg =false else{ pje = pj%10 pie = pi%10 } pi = pi/10 pj = pj/10 }while(pi != 0 && tg ) if(tg){ bf(id) += 1 if(bf(id) >= 8 ) res = pa(i) } j += 1 } i += 1 } println(res) }
问题52:Find the smallest positive integer, x, such that 2x, 3x, 4x, 5x, and 6x, contain the same digits in some order.
题目简介:求最小的x,使得x的2倍,3倍,4倍,5倍,6倍都是由相同的数字组成
答 案:142857
PS:对1/7的循环节印象比较深刻,直接就写出来了,果然是对的:-)
问题53:How many values of C(n,r), for 1 ≤ n ≤ 100, exceed one-million?
题目简介:求组合数C(n,r) (1 ≤ n ≤ 100)中超过1000000的有多少个。
答 案:4075
object Euler053 extends Application { var buf =new Array[BigInt](101) var res =0 for(row <- 0 to 100){ var pre =buf(0) for(col <- 1 to row-1){ var tmp =pre pre =buf(col) buf(col) += tmp if(buf(col)>1000000) res += 1 } buf(row) =1 } println(res) }
问题54:How many hands did player one win in the game of poker?
题目简介:一个扑克牌游戏,判断提供的数据中玩家1赢的盘数有多少次
答 案:376
import scala.io.Source._ object Euler054 extends Application { val src = fromFile("poker.txt").getLines var cnt = 0 src.foreach{ hand => val lst = hand.split("\\s").toList val aPlayer = new CardHand(lst.take(5)) val bPlayer = new CardHand(lst.drop(5)) if(aPlayer > bPlayer) cnt += 1 } println(cnt) } class CardHand(cards:List[String]) extends Ordered[CardHand] { val map = Map('2'->2,'3'->3,'4'->4,'5'->5,'6'->6,'7'->7, '8'->8,'9'->9,'T'->10,'J'->11,'Q'->12,'K'->13,'A'->14) val values = cards.map{c => map(c.first)}.sort{ _ > _ } def rank :List[Int] = { val isFlush = cards.forall{ _.last == cards.first.last } val isStraight = values.zipWithIndex.forall{ case(x,y) => x + y == values.first } if(isFlush && isStraight) return 9::values if(isFlush) return 6::values if(isStraight) return 5::values val lst = values.map{ v =>(values.filter{ _==v }.size,v) }.removeDuplicates.sort{ _ > _ } val vst = lst.map{ _._2 } if(lst.first._1 == 4) return 8::vst if(lst.first._1 == 3) return if(lst(1)._1 == 2) 7::vst else 4::vst if(lst.first._1 == 2) return if(lst(1)._1 == 2) 3::vst else 2::vst 1::values } def compare(that:CardHand):Int = rank compare that.rank }
问题55:
How many Lychrel numbers are there below ten-thousand?
题目简介:首先介绍一个数学名词:利克瑞尔数(Lychrel Number):指的是将该数与将该数各数位逆序翻转后形成的新数相加、并将此过程反复迭代后,结果永远无法是一个回文数的自然数。
现在已知对于10000以内的自然数,要么能够在50步(指将这个数与其逆序后的数相加的过程)内得到一个回文数;要么该数是一个利克瑞尔数。
求:10000以内利克瑞尔数的个数
答 案:249
import java.math.BigInteger object Euler055 extends Application { var res = 0 for(n <- 1 until 10000){ var b:BigInt = n var s = b.toString var r = s.reverse var k = 0 do{ b = b + BigInt(r) s = b.toString r = s.reverse k += 1 }while(!s.sameElements(r) && k <= 50) if(k > 50) res += 1 } println(res) }
问题56:Considering natural numbers of the form, a^b, finding the maximum digital sum.
题目简介:记f(x)表示自然数x的各位数字之和,a^b表示a的b次方。对1≤a,b <100,求f(a^b)的最大值。
答 案:972
//Scala val nums = for(a <- 1 to 100;b <- 1 to 100) yield (a:BigInt).pow(b) nums.map{ _.toString.foldLeft(0){ _+_-'0' } }.foldLeft(0){ _ max _ }
问题57:Investigate the expansion of the continued fraction for the square root of two.
题目简介:2的平方根有连分数的表示:√2 = 1 + 1/(2 + 1/(2 + 1/(2 + ... ))) = 1.414213...
展开其中的前四项为:
1 + 1/2 = 3/2 = 1.5
1 + 1/(2 + 1/2) = 7/5 = 1.4
1 + 1/(2 + 1/(2 + 1/2)) = 17/12 = 1.41666...
1 + 1/(2 + 1/(2 + 1/(2 + 1/2))) = 41/29 = 1.41379...
接下来的三项依次为:99/70, 239/169,577/408
而第八项是1393/985,注意,这是第一个出现分子位数超过分母位数的项(分子是4位数,而分母是3位数)
现在要求前1000项中,分子位数比分母位数多的个数。
答 案:153
object Euler057 extends Application { var res = 0 var a = BigInt(1) var b = BigInt(1) for(n <- 1 to 1000){ a = a + b + b b = a - b if(a.toString.length > b.toString.length) res += 1 } println(res) }
问题58:
Investigate the number of primes that lie on the diagonals of the spiral grid.
题目简介:将自然数按如下方式逆时针排列:
37 36 35 34 33 32 31
38 17 16 15 14 13 30
39 18 05 04 03 12 29
40 19 06 01 02 11 28
41 20 07 08 09 10 27
42 21 22 23 24 25 26
43 44 45 46 47 48 49
其中标红色的表示出现在对角线上且为素数的自然数,注意对角线上一共有13个自然数,其中8个为素数。也就是说素数所占的比例为 8/13 ≈ 62%.
将上述方阵继续排列下去,求使得对角线上素数比例小于10%的方阵的最小边长。
答 案:26241
object Euler058 extends Application { var ps:Stream[Int] = Stream.cons(2, Stream.from(3).filter{ n => ps.takeWhile(p => p*p <= n).forall(n%_ !=0) }) def isPrime(n:Int) = ps.takeWhile{ p => p*p<=n }.forall{ n%_ !=0 } val rate = 0.1 var count = 1 var primes = 0 var size = 1 var diag = 1 do{ size += 2 for(loop <- 1 to 4){ diag = diag + size -1 if(isPrime(diag)) primes += 1 } count += 4 }while(primes >= count*rate) println(size) }
问题59:
Using a brute force attack, can you decrypt the cipher using XOR encryption?
题目简介:使用暴力破解一段使用异或方式加密的英文文本。
答 案:107359
import scala.io.Source._ object Euler059 extends Application { def isLetter(c:Int):Boolean = " !\"'(),-.0123456789:;?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".indexOf(c) >= 0 var src = fromFile("cipher1.txt").getLine(1).split(",").map{ _.trim.toInt.toChar }.zipWithIndex var pw = for(idx <- 0 until 3) yield 'a'.to('z').find{ c => src.filter{ _._2%3 == idx }.forall{ s => isLetter(s._1^c) } }.get var sum = src.foldLeft(0){ (n,s) => n + (s._1^pw(s._2%3)) } println(sum) }
问题60:Find a set of five primes for which any two primes concatenate to produce another prime.
题目简介:自然数3, 7, 109, 673有着非常奇特的性质:
1.它们都是素数
2.它们任意两个连接而成的数也是素数。比如7与3相连得到73是素数
3.它们是满足上面两个性质并且使得和最小的一组数
现在要求5个素数使得其中任意两个连接得到的数也是素数,并且使这5个数之和最小。
输出这5个数之和
答 案:26033
import eastsun.math.Util._ import java.util.Arrays.binarySearch object Euler060 extends Application { //get primes below 100000000 val primes = getPrimes(100000000) def isPrime(n:Int) = binarySearch(primes,n) >= 0 //get intersection of la and lb,store in order def intersect(la:List[Int],lb:List[Int]):List[Int] = { var lx = la var ly = lb var ls:List[Int] = Nil while(!(lx.isEmpty || ly.isEmpty)){ var ix = lx.head var iy = ly.head if(ix >= iy) ly = ly.tail if(ix <= iy) lx = lx.tail if(ix == iy) ls = ix::ls } ls.reverse } def find(ls:List[Int]):Int = { var min = Integer.MAX_VALUE def find0(lx:List[Int],sum:Int,depth:Int){ if(lx.size < 4 - depth) return if(depth == 3) min = primes(lx.first)+ sum else lx.foreach{ x => find0(intersect(lx,items(x)),sum+primes(x),depth+1) } } find0(ls,0,0) min } val size = primes.findIndexOf{ _ >= 10000 } val items = new Array[List[Int]](size) for(i <- 0 until size){ var item = List[Int]() for(j <- i+1 until size){ var a = primes(i) var b = primes(j) if(isPrime((a+""+b).toInt) && isPrime((b+""+a).toInt) ) item = j::item } items(i) = item.reverse } var res = Integer.MAX_VALUE items.zipWithIndex.foreach{ iti => var f = find(iti._1) if(f < Integer.MAX_VALUE && f + primes(iti._2) < res) res = f + primes(iti._2) } println(res) }