project euler 69

Problem 69


Totient maximum

Euler’s Totient function, φ(n) [sometimes called the phi function], is used to determine the number of numbers less than n which are relatively prime to n. For example, as 1, 2, 4, 5, 7, and 8, are all less than nine and relatively prime to nine, φ(9)=6.

n Relatively Prime φ(n) n/φ(n)
2 1 1 2
3 1,2 2 1.5
4 1,3 2 2
5 1,2,3,4 4 1.25
6 1,5 2 3
7 1,2,3,4,5,6 6 1.1666…
8 1,3,5,7 4 2
9 1,2,4,5,7,8 6 1.5
10 1,3,7,9 4 2.5

It can be seen that n=6 produces a maximum n/φ(n) for n ≤ 10.

Find the value of n ≤ 1,000,000 for which n/φ(n) is a maximum.


欧拉总计函数与最大值

在小于n的数中,与n互质的数的数目记为欧拉总计函数φ(n)(有时也称为φ函数)。例如,因为1、2、4、5、7和8均小于9且与9互质,故φ(9)=6。

n 互质的数 φ(n) n/φ(n)
2 1 1 2
3 1,2 2 1.5
4 1,3 2 2
5 1,2,3,4 4 1.25
6 1,5 2 3
7 1,2,3,4,5,6 6 1.1666…
8 1,3,5,7 4 2
9 1,2,4,5,7,8 6 1.5
10 1,3,7,9 4 2.5

可以看出,对于n ≤ 10,当n=6时n/φ(n)取得最大值。

当n ≤ 1,000,000时,求使得n/φ(n)取得最大值的n。

package projecteuler;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import junit.framework.TestCase;

public class Prj69 extends TestCase {

	public static final int UP_LIMIT = 1000000;

	/**
	 * 欧拉函数phi(n)=n(1- 1/p1)(1-1/p2)...(1-1/pm);
	 */
	public void testTotientMaximum() {

		double max = 2;
		int maxId = 1;

		IntegerDivisor div = new IntegerDivisor();
		for (int i = 2; i <= UP_LIMIT; i++) {
			div.clear();
			div.divisor(i);
			List<Long> primeList = div.primeList;

			double val = 1;
			for (int j = 0; j < primeList.size(); j++) {
				int p = primeList.get(j).intValue();
				val = val * p / (p - 1);
			}
			if (val > max) {
				max = val;
				maxId = i;
			}
		}

		String fstr = "max=%s,n=%s";
		fstr = String.format(fstr, Double.toString(max),
				Integer.toString(maxId));
		System.out.println(fstr);
	}

	public void testTotientMaximumUseProperty() {

		int maxId = 1;
		for (int i = 2;; i++) {
			if (isPrime(i)) {
				
				if( maxId * i > UP_LIMIT){
					break;
				}
				maxId *= i;
			}
		}

		System.out.println(maxId);
	}

	private boolean isPrime(int i) {

		if (i <= 10) {
			if (i == 2 || i == 3 || i == 5 || i == 7) {
				return true;
			}
			return false;
		}

		if (i % 2 == 0) {
			return false;
		}

		for (int j = 3; j * j <= i; j++) {
			if (i % j == 0) {
				return false;
			}
		}

		return true;
	}

	public static class IntegerDivisor {

		public Map<Long, Integer> primeMap = new HashMap<Long, Integer>();
		public List<Long> primeList = new ArrayList<Long>();

		public void clear() {
			primeList.clear();
			primeMap.clear();
		}

		public void divisor(long num) {

			if (num <= 1)
				return;

			long prime = getPrime(
					num,
					primeList.size() == 0 ? 2
							: primeList.get(primeList.size() - 1));
			if (prime < 0) {
				primeMap.put(num, 1);
				primeList.add(num);
				return;
			} else {

				primeList.add(prime);
				int count = 0;
				do {

					count += 1;
					num = num / prime;
				} while (num % prime == 0);

				primeMap.put(prime, count);

				divisor(num);

			}

		}

		private long getPrime(long num, long start) {

			for (long i = start; i <= Math.sqrt(num); i++) {
				if (num % i == 0) {
					return i;
				}
			}
			return -1;
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值