一,试题B: 类斐波那契循环数
1.题目描述:
对于一个有n 位的十进制数N = d1d2d3 ... dn,可以生成一个类斐波那契数列S ,数列S 的前n 个数为{S1 = d1, S2 = d2, S3 = d3...,Sn = dn},数列S 的第k(k > n) 个数为Σk-1i=k-n Si。如果这个数N 会出现在对应的类斐波那契数列S中,那么N 就是一个类斐波那契循环数。
例如对于197,对应的数列S 为f1; 9; 7; 17; 33; 57; 107; 197; : : : g,197 出现在S 中,所以197 是一个类斐波那契循环数。
请问在0 至107 中,最大的类斐波那契循环数是多少?
2.实例:
略
3.思路:
在0至10^7范围内,最大的类斐波那契循环数(即Keith数)是925993。这类数的特性是它出现在由其各位数字生成的类斐波那契数列中。通过高效生成数列并检查每一步的值,可以验证该数满足条件。
4:代码:
import java.util.LinkedList;
public class Main {
public static void main(String[] args) {
// 从1e7向下遍历寻找最大的Keith数
long max = 10_000_000L;
for (long n = max; n >= 0; n--) {
if (isKeithNumber(n)) {
System.out.println(n);
return;
}
}
System.out.println(0); // 若未找到则输出0
}
private static boolean isKeithNumber(long N) {
String s = Long.toString(N);
int length = s.length();
// 一位数直接返回true
if (length == 1) return true;
int[] digits = new int[length];
for (int i = 0; i < length; i++) {
digits[i] = s.charAt(i) - '0';
}
// 检查全零情况
boolean allZero = true;
for (int d : digits) {
if (d != 0) {
allZero = false;
break;
}
}
if (allZero) return N == 0;
// 初始化队列和总和
LinkedList<Long> queue = new LinkedList<>();
long sum = 0;
for (int d : digits) {
long num = d;
queue.add(num);
sum += num;
}
if (sum == N) return true;
// 生成后续项并检查
while (true) {
long first = queue.poll();
long next = 2 * sum - first;
if (next < 0) return false; // 处理溢出
if (next == N) return true;
if (next > N) return false;
queue.add(next);
sum = next;
}
}
}