project euler 104

Pandigital Fibonacci ends

The Fibonacci sequence is defined by the recurrence relation:

F n = F n?1 + F n?2, where F 1 = 1 and F 2 = 1.

It turns out that F541, which contains 113 digits, is the first Fibonacci number for which the last nine digits are 1-9 pandigital (contain all the digits 1 to 9, but not necessarily in order). And F2749, which contains 575 digits, is the first Fibonacci number for which the first nine digits are 1-9 pandigital.

Given that Fk is the first Fibonacci number for which the first nine digits AND the last nine digits are 1-9 pandigital, find k.


两端为全数字的斐波那契数

斐波那契数列由如下递归关系生成:

F n = F n?1 + F n?2,其中F 1 = 1且F 2 = 1。

可以发现,包含有113位数字的F541是第一个后9位数字是1至9全数字(包含1至9所有的数字,但不一定按照从小到大的顺序)的斐波那契数,而包含有575位数字的F2749是第一个前9位数字是1至9全数字的斐波那契数。

若Fk是第一个前9位数字和后9位数字都是1至9全数字的斐波那契数,求k。

package projecteuler;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import junit.framework.TestCase;

public class Prj104 extends TestCase {

	public static final int TAIL_BITS = 9;

	public void testPandigitalFibonacciEnds() {

		int[] a = enLarge(int2Arr(1), TAIL_BITS);
		int[] b = enLarge(int2Arr(1), TAIL_BITS);

		int n = 2;
		while (true) {

			int[] c = add(a, b);
			a = Arrays.copyOf(b, TAIL_BITS);
			b = Arrays.copyOf(c, TAIL_BITS);
			n++;
			if (isHeadPandigital(getHead(n)) && isTailPandigital(c)) {
				System.out.println("num=" + n);
				break;
			}
		}
	}

	private boolean isTailPandigital(int[] c) {

		Set<Integer> set = new HashSet<Integer>();

		for (int i = 0; i < c.length; i++) {
			if (set.contains(c[i])) {
				return false;
			}
			set.add(c[i]);
		}
		return true;
	}

	String getHead(int n) {
		double v = fibonacci(n);
		v -= Math.floor(v);
		v = Math.pow(10.0, v);
		while (v < 100000000) {
			v *= 10;
		}
		return Integer.toString((int) v);
	}

	double fibonacci(int n) {
		return -0.5 * Math.log(5.0) / Math.log(10.0) + ((double) n)
				* Math.log((Math.sqrt(5.0) + 1) / 2) / Math.log(10.0);
	}

	boolean isHeadPandigital(String str) {
		if (str.length() < 9) {
			return false;
		}
		String head = str.substring(0, 9);
		assert (head.length() == 9);
		return head.length() == 9 && head.indexOf('1') != -1
				&& head.indexOf('2') != -1 && head.indexOf('3') != -1
				&& head.indexOf('4') != -1 && head.indexOf('5') != -1
				&& head.indexOf('6') != -1 && head.indexOf('7') != -1
				&& head.indexOf('8') != -1 && head.indexOf('9') != -1;
	}

	int[] add(int[] a, int[] b) {
		assert (a.length == b.length);
		int[] ret = new int[a.length];
		
		for( int i = 0 ; i < a.length; i ++){
			ret[i] = a[i] + b[i];
		}
		
		for( int j = a.length - 1; j > 0; j --){
			ret[j - 1] += ret[j] / 10;
			ret[j ] %= 10;
		}
		ret[0] %= 10;
		return ret;
	}

	int[] int2Arr(int val) {

		String str = Integer.toString(val, 10);
		int[] ret = new int[str.length()];
		for (int i = 0; i < ret.length; i++) {
			ret[i] = Integer.parseInt(String.valueOf(str.charAt(i)));
		}
		return ret;
	}

	int[] enLarge(int[] val, int bits) {

		assert (val.length <= bits);

		int[] ret = new int[bits];

		for (int i = bits - val.length, j = 0; i < bits; i++, j++) {
			ret[i] = val[j];
		}
		return ret;

	}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值