对一个十进制数的各位数字做一次平方和,称作一次迭代。如果一个十进制数能通过若干次迭代得到 1,就称该数为幸福数。1 是一个幸福数。此外,例如 19 经过 1 次迭代得到 82,2 次迭代后得到 68,3 次迭代后得到 100,最后得到 1。则 19 就是幸福数。显然,在一个幸福数迭代到 1 的过程中经过的数字都是幸福数,它们的幸福是依附于初始数字的。例如 82、68、100 的幸福是依附于 19 的。而一个特立独行的幸福数,是在一个有限的区间内不依附于任何其它数字的;其独立性就是依附于它的的幸福数的个数。如果这个数还是个素数,则其独立性加倍。例如 19 在区间[1, 100] 内就是一个特立独行的幸福数,其独立性为 2×4=8。
另一方面,如果一个大于1的数字经过数次迭代后进入了死循环,那这个数就不幸福。例如 29 迭代得到 85、89、145、42、20、4、16、37、58、89、…… 可见 89 到 58 形成了死循环,所以 29 就不幸福。
本题就要求你编写程序,列出给定区间内的所有特立独行的幸福数和它的独立性。
输入格式:
输入在第一行给出闭区间的两个端点:1<A<B≤10
4
。
输出格式:
按递增顺序列出给定闭区间 [A,B] 内的所有特立独行的幸福数和它的独立性。每对数字占一行,数字间以 1 个空格分隔。
如果区间内没有幸福数,则在一行中输出 SAD。
输入样例 1:
10 40
输出样例 1:
19 8
23 6
28 3
31 4
32 3
注意:样例中,10、13 也都是幸福数,但它们分别依附于其他数字(如 23、31 等等),所以不输出。其它数字虽然其实也依附于其它幸福数,但因为那些数字不在给定区间 [10, 40] 内,所以它们在给定区间内是特立独行的幸福数。
输入样例 2:
110 120
输出样例 2:
SAD
建立2个数组,一个数组标记未处理处理过(0)、不幸福数(1)、不幸福的数字(2)、特立独行的幸福数(3),另外一个数组标记依赖数字的数量。
这里我将2个数组合到一起,用的是一个两列的二维数组,标记依赖数量和数字的类型的方式是用的回溯
废话不多说,注释都有
题目传送门:https://pintia.cn/problem-sets/994805046380707840/problems/1111914599412858886
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
Reader.init(System.in);
a = Reader.nextInt();
b = Reader.nextInt();
luck = new int[10001][2];
// 对每个数字进行判断
for (int i = a; i <= b; i++) {
// 判断是否处理过,没有处理过的是0
if (luck[i][0] == 0) {
// 记录下位置当前处理的数字
index = i;
// 判断是否是幸福数 若是 则这个数字是特立独行的幸福数
if(fun(i) == 2) {
luck[i][0] = 3;
}
}
}
// 输出结果
boolean have = false;
for (int i = a; i <= b; i++) {
// 若是是特立独行的幸福数,则进行素数判断并输出
if (luck[i][0] == 3) {
have = true;
if (isPrime(i)) {
System.out.println(i + " " + (2 * luck[i][1]));
} else {
System.out.println(i + " " + luck[i][1]);
}
}
}
if (!have) {
System.out.println("SAD");
}
}
// 区间
static int a, b;
// 第一位用来标记当前数字是否幸福数,其中一表示是不幸福数,二表示是幸福数,三表示幸福数
// 第二位用来记录依赖数
static int[][] luck;
static int index;
static int count;
static int fun(int val) {
// 判断当前数字是不是幸福数
if (val == 1 || luck[val][0] == 2 || luck[val][0] == 3) {
// 记录层数,回溯时给每个幸福数确定依赖数字
luck[index][1] = luck[val][1];
// System.out.println("============luck============");
return luck[val][0] = 2;
}
// 判断当前数字是不是不幸福数字,由于幸福数字已经判断过了,则只要当前数字是被处理过的,则一定是不幸福的数字
if (luck[val][0] != 0) {
// System.out.println("------------unluck------------");
return 1;
}
// 计算平方和,结果放入sum
int sum = 0;
int current = val;
int factor = 0;
while (current != 0) {
factor = current % 10;
sum += factor * factor;
current /= 10;
}
// System.out.println(val + "->"+sum);
// 先标记已经处理过,默认标记为不幸福数字
luck[val][0] = 1;
// 判断当前数字是幸福数字还是不幸福数字,二表示幸福数字,一表示不幸福数字
luck[val][0] = fun(sum);
// 回溯给出依赖数量
luck[val][1] = ++luck[index][1];
return luck[val][0];
}
public static boolean isPrime(int m) {
if (m == 1) {
return false;
}
// 2 、 3 单独处理
if (m == 2 || m == 3) {
return true;
}
// 不在6的倍数两边的一定不是素数
if (m % 6 != 1 && m % 6 != 5) {
return false;
}
int sqrt_m = (int) Math.sqrt(m);
// 在6的倍数两侧的也可能不是素数
for (int i = 5; i <= sqrt_m; i += 6) {
if (m % i == 0 || m % (i + 2) == 0) {
return false;
}
}
// 排除所有 剩下就是素数了
return true;
}
}
// Class for buffered reading int and double values *//*
class Reader {
static BufferedReader reader;
static StringTokenizer tokenizer;
// ** call this method to initialize reader for InputStream *//*
static void init(InputStream input) {
reader = new BufferedReader(new InputStreamReader(input));
tokenizer = new StringTokenizer("");
}
static void init(File file) {
try {
reader = new BufferedReader(new FileReader(file));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
tokenizer = new StringTokenizer("");
}
// ** get next word *//*
static String next() throws IOException {
while (!tokenizer.hasMoreTokens()) {
// TODO add check for eof if necessary
tokenizer = new StringTokenizer(reader.readLine());
}
return tokenizer.nextToken();
}
static String nextLine() throws IOException {
return reader.readLine();
}
static int nextInt() throws IOException {
return Integer.parseInt(next());
}
static char nextChar() throws IOException {
return next().toCharArray()[0];
}
static float nextFloat() throws IOException {
return Float.parseFloat(next());
}
static Double nextDouble() throws IOException {
return Double.parseDouble(next());
}
}