题目描述
从任一给定的正整数 n 出发,将其每一位数字相乘,记得到的乘积为 n1。以此类推,令 ni+1 为 ni 的各位数字的乘积,直到最后得到一个个位数 nm,则 m 就称为 n 的持续性。例如 679 的持续性就是 5,因为我们从 679 开始,得到 6×7×9=378,随后得到 3×7×8=168、1×6×8=48、4×8=32,最后得到 3×2=6,一共用了 5 步。
本题就请你编写程序,找出任一给定区间内持续性最长的整数。
输入格式:
输入在一行中给出两个正整数 a 和 b(1≤a≤b≤且 (b−a)<
),为给定区间的两个端点。
输出格式:
首先在第一行输出区间 [a,b] 内整数最长的持续性。随后在第二行中输出持续性最长的整数。如果这样的整数不唯一,则按照递增序输出,数字间以 1 个空格分隔,行首尾不得有多余空格。
输入样例:
500 700
输出样例:
5
679 688 697
代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB
栈限制 8192 KB
解题思路
读题发现b-a<1000,考虑暴力在[a, b]循环模拟找出最大值。
定义一个方法
int getPerNumSum(int num)
这个方法传入一个整数,返回每一位数字相乘的结果。
循环遍历[a, b]的每一个数,计算其持续性
不能够持续的终止条件是每一位数字相乘的结果=传入的数
最后判断最大持续性与当前持续性的关系。
下面是核心部分代码:
ArrayList<Integer> res = new ArrayList<>();
// 暴力模拟
for (int i = a; i <= b; i++) {
// 持续性计数
int count = 0;
int j = i;
int l = j;
// 当模拟到的数等于上一个模拟的数时,终止循环
while ((j = getPerNumSum(j)) != l) {
count++;
l = j;
}
// 当持续性相同时,向答案list添加
if (max == count) {
res.add(i);
} else if (count > max) {
// 当发现有更大的持续性时, 清除list元素并记录新的元素
max = count;
res.clear();
res.add(i);
}
}
这里提一下怎么快速获取一个正整数(如果获取负数则把负数变为正数)的每一位数字的方法
对于c++或java,除号(/)指的是整除,即两整数整除,会去除结果的小数部分,保留整数部分。
也就是说
一个整数对10求余后=该整数的个位,例如1001%10=1
一个整数整除10后=去除整数的个位部分,例如1001/10=100
下面代码中的perNum就是数字的每一位
private static void getPerNum(int num) {
while (num > 0) {
int perNum = num % 10; // 每一位数字,从个位到最高位
num /= 10;
}
}
在这个题目中,我们要获取的是一个正整数的每一位的乘积。
定义一个res=1变量,保存每一位的乘积,在循环中相乘每一位。
在这里一定要注意传入的num = 0的情况,因为0的每一位相乘=0!!!
private static int getPerNumSum(int num) {
int sum = 1;
if (num == 0) return 0;
while (num > 0) {
sum *= num % 10;
num /= 10;
}
return sum;
}
实现代码
import java.io.*;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) throws Exception {
int a = readInt();
int b = readInt();
int max = Integer.MIN_VALUE;
// 使用一个list装答案输出
ArrayList<Integer> res = new ArrayList<>();
// 暴力模拟
for (int i = a; i <= b; i++) {
// 连续性计数
int count = 0;
int j = i;
int l = j;
// 当模拟到的数等于上一个模拟的数时,终止循环
while ((j = getPerNumSum(j)) != l) {
count++;
l = j;
}
// 当连续性相同时,向答案list添加
if (max == count) {
res.add(i);
} else if (count > max) {
// 当发现有更大的连续性时, 清除list元素并记录新的元素
max = count;
res.clear();
res.add(i);
}
}
// 输出
System.out.println(max);
// 尾部不包含空格
System.out.println(res.stream().map(String::valueOf).collect(Collectors.joining(" ")));
}
/**
* 提取每一位, 返回各位数字相乘
*/
private static int getPerNumSum(int num) {
int sum = 1;
if (num == 0) return 0;
while (num > 0) {
sum *= num % 10;
num /= 10;
}
return sum;
}
private static void getPerNum(int num) {
while (num > 0) {
int perNum = num % 10; // 每一位数字,从个位到最高位
num /= 10;
}
}
// region 设置系统输入流为stdin.txt文件,输出流为stdout.txt
static {
// try {
// System.setIn(new FileInputStream("stdin.txt"));
// System.setOut(new PrintStream("stdout.txt"));
// } catch (FileNotFoundException e) {
// throw new RuntimeException(e);
// }
}
// endregion 设置系统输入流为stdin.txt,输出流为stdout.txt
// region 快速输入输出对象
/**
* 输入流
*/
public static final Scanner sc = new Scanner(System.in);
public static final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
public static final StreamTokenizer st = new StreamTokenizer(br);
public static final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
private static int readInt() {
try {
st.nextToken();
return (int) st.nval;
} catch (Exception ignored) {
}
return -1;
}
private static double readDouble() {
try {
st.nextToken();
return st.nval;
} catch (Exception ignored) {
}
return -1;
}
private static String readString() {
try {
st.nextToken();
return st.sval;
} catch (Exception ignored) {
}
return "";
}
/**
* 配置st读取数字字符串
*/
private static void parseLongNumber() {
st.ordinaryChars('0', '9');
st.wordChars('0', '9');
}
private static long readLong() {
try {
st.nextToken();
return Long.parseLong(st.sval);
} catch (Exception ignored) {
}
return -1;
}
// endregion end 快速输入输出对象
}