【Java算法】团体程序设计天梯赛L1-103 整数的持续性

题目描述

从任一给定的正整数 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≤10^{9}且 (b−a)<10^{3}),为给定区间的两个端点。

输出格式:

首先在第一行输出区间 [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 快速输入输出对象
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值