Project euler problem 21 - 30

Problem 21
原题:

Let d(n) be defined as the sum of proper divisors of n (numbers less than n which divide evenly into n).
If d(a) = b and d(b) = a, where a b, then a and b are an amicable pair and each of a and b are called amicable numbers.

For example, the proper divisors of 220 are 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 and 110; therefore d(220) = 284. The proper divisors of 284 are 1, 2, 4, 71 and 142; so d(284) = 220.

Evaluate the sum of all the amicable numbers under 10000.


分析:亲和数,事实上在10000下面只有

代码:

  1.     // 表示总积
  2.     private static int total = 0;

  3.     public static void findAmicableNubmers(int num) {
  4.         int sum = sumOfDivisors(num);
  5.         if (sum >= 10000 || sum <= num) {
  6.             return;
  7.         }
  8.         if (num == sumOfDivisors(sum)) {
  9.             total += sum;
  10.             total += num;
  11.         }
  12.     }

  13.     // 返回num的真因子和
  14.     public static int sumOfDivisors(int num) {
  15.         int sum = 1;
  16.         int sqrt = (int) Math.sqrt(num);
  17.         for (int i = 2; i <= sqrt; i++) {
  18.             if (num % i == 0) {
  19.                 sum += i;
  20.                 sum += num / i;
  21.             }
  22.         }
  23.         if (num == sqrt * sqrt) {
  24.             sum -= sqrt;
  25.         }

  26.         return sum;
  27.     }

  28.     public static void main(String[] args) {
  29.         for (int i = 220; i < 10000; i++)
  30.             findAmicableNubmers(i);
  31.         System.out.println(total);
  32.     }
Problem 22

原题:

Using names.txt (right click and 'Save Link/Target As...'), a 46K text file containing over five-thousand first names, begin by sorting it into alphabetical order. Then working out the alphabetical value for each name, multiply this value by its alphabetical position in the list to obtain a name score.

For example, when the list is sorted into alphabetical order, COLIN, which is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name in the list. So, COLIN would obtain a score of 938 53 = 49714.

What is the total of all the name scores in the file?


分析:names.txt里面包含5000个名,首先将这些名字按字母排序,然后再计算它们的分数。每个名字的分数的计算方式如下:先把名字的每个字母所在字母表中的位置相加,所得的和再乘以该名字在所排序好数组中的位置。硬算呗。。

代码:

  1.     private static String[] ss;
  2.     // 初始化数组,读取文件并排序
  3.     private static void read() throws Exception {
  4.         BufferedReader br = new BufferedReader(new FileReader(
  5.                 "names.txt"));
  6.         String line = br.readLine().replace("/"""");
  7.         br.close();
  8.         ss = line.split(",");
  9.         Arrays.sort(ss);
  10.     }
  11.     // 计算每个名字的分数并相加
  12.     private static int calc() {
  13.         int sum = 0;
  14.         for (int i = 0; i < ss.length; i++) {
  15.             int temp = 0;
  16.             char[] cs = ss[i].toCharArray();
  17.             for (char c : cs) {
  18.                 temp += (c + 1 - 'A');
  19.             }
  20.             sum += ((i + 1) * temp);
  21.         }
  22.         return sum;
  23.     }
  24.     public static void main(String[] args) throws Exception {
  25.         read();
  26.         int sum = calc();
  27.         System.out.println(sum);
  28.     }
Problem 23
原题:

A perfect number is a number for which the sum of its proper divisors is exactly equal to the number. For example, the sum of the proper divisors of 28 would be 1 + 2 + 4 + 7 + 14 = 28, which means that 28 is a perfect number.

A number whose proper divisors are less than the number is called deficient and a number whose proper divisors exceed the number is called abundant.

As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the smallest number that can be written as the sum of two abundant numbers is 24. By mathematical analysis, it can be shown that all integers greater than 28123 can be written as the sum of two abundant numbers. However, this upper limit cannot be reduced any further by analysis even though it is known that the greatest number that cannot be expressed as the sum of two abundant numbers is less than this limit.

Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers.


分析:盈数,完美数(完全数?),亏数。这里求的是所有不能写成两个盈数的整数的和(题中给出提示,28123以上的数都能写成两个盈数之和)
代码:
  1. // 用来存储盈数
  2.     private static List<Integer> nums = new ArrayList<Integer>();
  3.     private static void findAbundantNumber() {
  4.         for (int i = 12; i <= 30000; i++) {
  5.             if (sumOfDivisors(i) > i) {
  6.                 nums.add(i);
  7.             }
  8.         }
  9.     }
  10.     // 返回:num的真因子之和
  11.     public static int sumOfDivisors(int num) {
  12.         int sum = 1;
  13.         int sqrt = (int) Math.sqrt(num);
  14.         for (int i = 2; i <= sqrt; i++) {
  15.             if (num % i == 0) {
  16.                 sum += i;
  17.                 sum += num / i;
  18.             }
  19.         }
  20.         if (num == sqrt * sqrt) {
  21.             sum -= sqrt;
  22.         }
  23.         return sum;
  24.     }
  25.     public static void main(String[] args) {
  26.         findAbundantNumber();
  27.         int sum = 0;
  28.         for (int i = 1; i <= 30000; i++) {
  29.             boolean isA = false;
  30.             for (int num : nums) {
  31.                 // 如果第一个数已经大于待求的一半,则返回
  32.                 if (num > i / 2) {
  33.                     break;
  34.                 }
  35.                 // 第二个数
  36.                 int num2 = i - num;
  37.                 // 如果第二个数也是盈数
  38.                 if (Collections.binarySearch(nums, num2) >= 0) {
  39.                     isA = true;
  40.                     break;
  41.                 }
  42.             }
  43.             if (!isA) {
  44.                 sum += i;
  45.                 System.out.println(i);
  46.             }
  47.         }
  48.         System.out.println(sum);
  49.     }
Problem 24
原题:

A permutation is an ordered arrangement of objects. For example, 3124 is one possible permutation of the digits 1, 2, 3 and 4. If all of the permutations are listed numerically or alphabetically, we call it lexicographic order. The lexicographic permutations of 0, 1 and 2 are:

012   021   102   120   201   210

What is the millionth lexicographic permutation of the digits 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9?

分析:0123456789我们知道有10!个不同的排序,如果按字典排序,求第1000000个数字是多少?这题用笔和纸即可完成,只是有点麻烦了,首先确定第一位,0开头的一共有9!个排序,1....9同样,所以,第一个数字可确定为999999/9!,即为2。等同于求013456789的第(999999-2 * 9!)位的排序,按照确定第一位的方法,一样解决了

代码:

  1.     public static void p() {
  2.         // 阶乘数组
  3.         int[] factorial = { 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 };
  4.         String s = "0123456789";
  5.         int l = 999999;
  6.         String s1 = "";
  7.         for (int i = factorial.length - 1; i >= 0; i--) {
  8.             // 应该取剩下字符串的第几位
  9.             int num = l / factorial[i];
  10.             s1 += s.charAt(num);
  11.             l = l - num * factorial[i];
  12.             // 把确定的数从字符串中移取
  13.             s = doff(s, num);
  14.         }
  15.         System.out.println(s1 + s);
  16.     }

  17.     // 确定一位后,剩下的数
  18.     private static String doff(String s, int index) {
  19.         return s.substring(0, index) + s.substring(index + 1);
  20.     }

  21.     public static void main(String[] args) {
  22.         p();
  23.     }
Problem 25

原题:

The Fibonacci sequence is defined by the recurrence relation:

F n = F n1 + F n2, where F 1 = 1 and F 2 = 1.

Hence the first 12 terms will be:

F 1 = 1
F 2 = 1
F 3 = 2
F 4 = 3
F 5 = 5
F 6 = 8
F 7 = 13
F 8 = 21
F 9 = 34
F 10 = 55
F 11 = 89
F 12 = 144

The 12th term, F12, is the first term to contain three digits.

What is the first term in the Fibonacci sequence to contain 1000 digits?

分析:Fibonacc(斐波那契)数列,求的是第一个长度超过1000的数

利用公式 an = {[(1 + √5)/2]^n - [(1 - √5)/2]^n}/√5,本来是想直接利用数学公式进行求,结果发现无从下手,直好用了类似二分查找的方法。随便设了一个上限5000,结果碰上死耗子,搞定。耗死将近2分钟,有兴趣的想别的办法,总觉得能用数学公式一次求出来,直接用计算机就可求出此题的解。


代码:

  1.     // an = {[(1 + √5)/2]^n - [(1 - √5)/2]^n}/√5
  2.     private static final BigDecimal sqrt5 = BigDecimal
  3.             .valueOf(Math.sqrt(5));

  4.     private static final BigDecimal one = BigDecimal.ONE;

  5.     private static final BigDecimal num1 = one.add(sqrt5).divide(
  6.             BigDecimal.valueOf(2));
  7.     private static final BigDecimal num2 = one.subtract(sqrt5).divide(
  8.             BigDecimal.valueOf(2));

  9.     private static int getLength(int n) {
  10.         BigDecimal result = num1.pow(n).subtract(num2.pow(n));
  11.         result = result.divide(sqrt5);
  12.         return result.toBigInteger().toString().length();
  13.     }

  14.     public static void main(String[] args) {
  15.         int min = 1;
  16.         int max = 5000;
  17.         while (min < max - 1) {
  18.             int middle = (min + max) / 2;
  19.             System.out.printf("%d,%d,%d/n", min, middle, max);
  20.             int len = getLength(middle);
  21.             if (len < 1000) {
  22.                 min = middle;
  23.             } else {
  24.                 max = middle;
  25.             }
  26.         }
  27.         System.out.println(max);
  28.     }
Problem 26

原题

A unit fraction contains 1 in the numerator. The decimal representation of the unit fractions with denominators 2 to 10 are given:

1/20.5
1/30.(3)
1/40.25
1/50.2
1/60.1(6)
1/70.(142857)
1/80.125
1/90.(1)
1/100.1

Where 0.1(6) means 0.166666..., and has a 1-digit recurring cycle. It can be seen that 1/7 has a 6-digit recurring cycle.

Find the value of d 1000 for which 1/d contains the longest recurring cycle in its decimal fraction part.

分析:d<1000,求1/d最长的无限循环部分长度。

其实就是记录每次的余数,如果发现该余数在前面已经出现,则说明一个循环部分。

代码:

  1.     public static int r(int b) {
  2.         List<Integer> l = new ArrayList<Integer>();
  3.         int a = 1;
  4.         l.add(a);
  5.         int count = 1;
  6.         do {
  7.             a = (a * 10) % b;
  8.             if (a == 0) {
  9.                 return 0;
  10.             }
  11.             int index = l.indexOf(a);
  12.             if (index > -1) {
  13.                 return count - index;
  14.             } else {
  15.                 l.add(a);
  16.                 count++;
  17.             }
  18.         } while (true);
  19.     }

  20.     public static void main(String[] args) {
  21.         int max = 0;
  22.         for (int i = 1; i < 1000; i++) {
  23.             int temp = r(i);
  24.             if (temp > max) {
  25.                 System.out.printf("%d/t%d/n", i, temp);
  26.                 max = temp;
  27.             }
  28.         }
  29.     }
Problem 27

原题:

Euler published the remarkable quadratic formula:

n² + n + 41

It turns out that the formula will produce 40 primes for the consecutive values n = 0 to 39. However, when n = 40, 402 + 40 + 41 = 40(40 + 1) + 41 is divisible by 41, and certainly when n = 41, 41² + 41 + 41 is clearly divisible by 41.

Using computers, the incredible formula  n² 79n + 1601 was discovered, which produces 80 primes for the consecutive values n = 0 to 79. The product of the coefficients, 79 and 1601, is 126479.

Considering quadratics of the form:

n² + an + b, where | a| 1000 and | b| 1000

where | n| is the modulus/absolute value of n
e.g. |11| = 11 and | 4| = 4

Find the product of the coefficients, a and b, for the quadratic expression that produces the maximum number of primes for consecutive values of n, starting with n = 0.

分析:n² + an + b, where |a| 1000 and |b| 1000,使得他们能够满足[0,n]均为素数,当n最大时,求a * b的积,穷举吧,当然,加两个小小判断,b必须是素数,1 + a +b必须是素数。

代码:

  1.     private static boolean isPrime(int num) {
  2.         num = num > 0 ? num : -num;
  3.         if (num == 0 || num == 1) {
  4.             return false;
  5.         }
  6.         if (num == 2) {
  7.             return true;
  8.         }
  9.         for (int i = 2; i <= Math.sqrt(num); i++) {
  10.             if (num % i == 0) {
  11.                 return false;
  12.             }
  13.         }
  14.         return true;
  15.     }

  16.     private static int getPrimes(int a, int b) {
  17.         for (int i = 0; i < 1000; i++) {
  18.             if (!isPrime(i * i + a * i + b)) {
  19.                 return i + 1;
  20.             }
  21.         }
  22.         return 1000;
  23.     }

  24.     public static void main(String[] args) {
  25.         int max = 0;
  26.         int result = 0;
  27.         for (int b = -999; b < 1000; b++) {
  28.             if (!isPrime(b)) {
  29.                 continue;
  30.             }

  31.             for (int a = -999; a < 1000; a++) {
  32.                 if (!isPrime(1 + a + b)) {
  33.                     continue;
  34.                 }
  35.                 int temp = getPrimes(a, b);
  36.                 if (temp > max) {
  37.                     max = temp;
  38.                     result = a * b;
  39.                     System.out.printf("%d * %d = %d, %d/n",
  40.                             a, b, result, temp);
  41.                 }
  42.             }
  43.         }
  44.     }
Problem 28

原题

Starting with the number 1 and moving to the right in a clockwise direction a 5 by 5 spiral is formed as follows:

21 22 23 24 25
20  7  8  9 10
19  6  1  2 11
18  5  4  3 12
17 16 15 14 13

It can be verified that the sum of both diagonals is 101.

What is the sum of both diagonals in a 1001 by 1001 spiral formed in the same way?

分析:在如图螺旋状的矩阵中,当矩阵大小为1001*1001时,将每层的四个角相加,所得和为多少?

首先,将“层”规定一下,当中的1叫第1层,2~9叫第3层,10~25叫第5层(其实就是跟矩阵的大小等同叫法)。这样的话,第n层的四个数分别为n*n, n*n - (n-1), n*n - 2(n-1), n*n - 3(n-1)。

这样,第n层的和为:4 * n * n  - 6n - 6(n>1且为奇数),第一层就是1,如果继续化简下去,用到奇数的平方和等公式,最后将是只是一个公式,这里就懒一点,算到这为止。

代码:

  1.     // 算第n层的和
  2.     private static int sum(int n) {
  3.         if (n == 1) {
  4.             return 1;
  5.         }

  6.         return 4 * n * n - 6 * n + 6;
  7.     }

  8.     public static void main(String[] args) {
  9.         int sum = 0;
  10.         int max = 1001;
  11.         for (int i = 1; i <= max; i += 2) {
  12.             sum += sum(i);
  13.         }
  14.         System.out.println(sum);
  15.     }
Problem 29

原题

Consider all integer combinations of ab for 2 a 5 and 2 b 5:

2 2=4, 2 3=8, 2 4=16, 2 5=32
3 2=9, 3 3=27, 3 4=81, 3 5=243
4 2=16, 4 3=64, 4 4=256, 4 5=1024
5 2=25, 5 3=125, 5 4=625, 5 5=3125

If they are then placed in numerical order, with any repeats removed, we get the following sequence of 15 distinct terms:

4, 8, 9, 16, 25, 27, 32, 64, 81, 125, 243, 256, 625, 1024, 3125

How many distinct terms are in the sequence generated by ab for 2 a 100 and 2 b 100?


分析:2 a 100 and 2 b 100?,求ab共有多少个不重复的值。嘿嘿,邪恶地暴力。

代码:

  1.     public static void distinctTerms() {
  2.         int max = 100;
  3.         Map<BigDecimal, Object> m = new HashMap<BigDecimal, Object>();
  4.         for (int a = 2; a <= max; a++) {
  5.             for (int b = 2; b <= max; b++) {
  6.                 BigDecimal r = BigDecimal.valueOf(a).pow(b);
  7.                 m.put(r, null);
  8.             }
  9.         }
  10.         System.out.println(m.size());
  11.     }
  12.     
  13.     public static void main(String[] args) {
  14.         distinctTerms();
  15.     }
Problem 30

原题:

Surprisingly there are only three numbers that can be written as the sum of fourth powers of their digits:

1634 = 1 4 + 6 4 + 3 4 + 4 4
8208 = 8 4 + 2 4 + 0 4 + 8 4
9474 = 9 4 + 4 4 + 7 4 + 4 4

As 1 = 14 is not a sum it is not included.

The sum of these numbers is 1634 + 8208 + 9474 = 19316.

Find the sum of all the numbers that can be written as the sum of fifth powers of their digits.


分析:有这样的数,它正好等于它每一位数字5次方的和,问所有这样的数和为多少?

简单分析,可知,这样的数,小于10的6次方

所以代码就简单地出来了,暴力吧

  1.     public static int find() {
  2.         int sum = 0;
  3.         for (int i = 2; i < 1000000; i++) {
  4.             if (i == pow(i)) {
  5.                 sum += i;
  6.                 System.out.println(i);
  7.             }
  8.         }
  9.         return sum;
  10.     }
  11.     private static int[] fifthPow = { 013224310243125777616807,
  12.             3276859049 };
  13.     public static int pow(int i) {
  14.         int sum = 0;
  15.         char[] cs = String.valueOf(i).toCharArray();
  16.         for (char c : cs) {
  17.             sum += fifthPow[c - '0'];
  18.         }
  19.         return sum;
  20.     }
  21.     public static void main(String[] args) {
  22.         System.out.println(find());
  23.     }

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值