天梯刷题练习(6-10)(Java)

 团体程序设计天梯赛-练习集

L1-006 连续因子

连续因子探测算法

  1. 遍历起点:从2到√n尝试每个数字作为连续因子链起点
  2. 计算链长:对每个起点,通过连续除法检测能分解n的最大连续数字链
  3. 质数特判:若无连续因子链(res=0),说明n是质数,直接输出自身
  4. 格式化输出:最长链长 + 用"*"连接的因子序列
import java.io.*;
import java.util.*;

public class Main {
    static BufferedReader sc = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
    static String[] ss; 
    static String s;    

    public static void main(String[] args) throws IOException {
        pre(); 
        int T = 1; 
        while (T-- > 0) solve(); 
        sc.close();  
        out.flush(); 
        out.close(); 
    }

    
    private static void pre() throws IOException {}

    
    static long MOD = 1000000007;

    public static void solve() throws IOException {
        int n = Integer.parseInt(sc.readLine());
        int res = 0; // 最长连续因子链长度
        int l = 1;   // 最长链的起始数字
        
        // 遍历所有可能的连续因子起点(2到√n)
        for (int i = 2; i <= Math.sqrt(n); i++) {
            int temp = n;  // 当前待分解数
            int cnt = 0;   // 当前连续因子计数
            
            // 检查连续因子链:i, i+1, i+2...
            for (int j = i; temp != 0 && temp % j == 0; j++) {
                temp /= j; // 分解数字
                cnt++;     // 链长增加
            }
            
            // 更新最长记录
            if (cnt > res) {
                res = cnt;
                l = i; // 记录新起点
            }
        }

        // 处理质数情况(最长链长为1的特殊输出)
        if (res == 0) {
            out.println("1");
            out.print(n);
        } 
        // 正常情况输出(格式:长度+因子链)
        else {
            out.println(res);
            StringBuilder sb = new StringBuilder().append(l);
            for (int i = l+1; i < l+res; i++) sb.append("*").append(i);
            out.print(sb);
        }
    }
}

L1-007 念数字 

映射表直接转换法

  1. 预定义字典:用HashMap存储字符到拼音的映射(包含负号)
  2. 分段输出:前n-1个字符输出"拼音+空格",最后一个单独输出避免末尾空格
  3. 时间复杂度:O(n)线性遍历,每个字符只需一次哈希表查询

关键技巧:通过分开处理最后一位解决格式化输出难题)

import java.io.*;
import java.util.*;

public class Main {

    static BufferedReader sc = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
    

    static String[] ss;
    static String s;

    public static void main(String[] args) throws IOException {
        String num = sc.readLine(); // 读取输入数字字符串
        
        // 创建数字到拼音的映射表(含负号处理)
        Map<Character, String> res = new HashMap<>();
        res.put('-', "fu");
        res.put('0', "ling");
        res.put('1', "yi");
        res.put('2', "er");
        res.put('3', "san");
        res.put('4', "si");
        res.put('5', "wu");
        res.put('6', "liu");
        res.put('7', "qi");
        res.put('8', "ba");
        res.put('9', "jiu");

        int len = num.length();
        // 遍历处理前n-1个字符:输出拼音+空格
        for(int i=0;i<len-1;i++) {
            char c = num.charAt(i);
            if(res.containsKey(c)) {
                out.print(res.get(c)+" ");
            }
        }
        // 单独处理最后一个字符:避免末尾多余空格
        out.println(res.get(num.charAt(len-1)));

        sc.close();
        out.flush();
        out.close();
    }
}


L1-008 求整数段和 

格式化输出三步法

  1. 区间遍历:从A到B逐个数字累加求和
  2. 格式控制:每个数占5字符宽度(%5d),每满5个自动换行
  3. 边缘处理:最后无论是否满5个都补换行,确保"Sum="另起行
import java.io.*;
import java.util.*;

public class Main {

    static BufferedReader sc = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
    static String[] ss; // 输入分割缓存
    static String s;    // 单行输入缓存

    public static void main(String[] args) throws IOException {
        // 读取输入并分割为A、B两个整数
        ss = sc.readLine().split(" ");
        int A = Integer.parseInt(ss[0]);
        int B = Integer.parseInt(ss[1]);
        
        int sum = 0;    // 累计总和
        int count = 0;  // 当前行数字计数器
        
        // 主循环:遍历区间[A,B]的所有数字
        for (int i = A; i <= B; i++) {
            sum += i; // 累加求和
            out.printf("%5d", i); // 每个数字占5字符宽度(右对齐)
            count++;
            
            // 每满5个数字换行(包括最后一行的完整换行)
            if (count % 5 == 0) out.println(); 
        }
        
        // 补足最后一行的换行(当最后一行不足5个时)
        if (count % 5 != 0) out.println(); 
        
        // 输出总和(格式严格匹配题目要求)
        out.print("Sum = " + sum);

        sc.close();
        out.flush();
        out.close();
    }
}

L1-009 N个数求和 

分步累加化简法

  1. 初始化:读取第一个分数并化简
  2. 逐次累加
    • 通分计算:新分子 = a*y + x*b新分母 = b*y
    • 立即化简:用最大公约数约分,确保分母为正
  3. 输出决策
    • 整数 → 直接输出
    • 假分数 → 转为带分数(如5/2 → 2 1/2
    • 真分数 → 直接输出(如3/4

核心优化:每次运算后立即约分,避免数值溢出,确保计算稳定性。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt();  // 读取分数个数
        long a = 0, b = 1;          // 累加结果的分子和分母
        
        // 处理第一个分数(单独处理避免循环边界问题)
        String[] firstFraction = scanner.next().split("/");
        a = Long.parseLong(firstFraction[0]);
        b = Long.parseLong(firstFraction[1]);
        long[] simplified = simplifyFraction(a, b);  // 初始化简化结果
        a = simplified[0];
        b = simplified[1];
        
        // 逐个累加后续分数
        for (int i = 1; i < N; i++) {
            String[] fraction = scanner.next().split("/");
            long x = Long.parseLong(fraction[0]); // 当前分子
            long y = Long.parseLong(fraction[1]); // 当前分母
            
            // 分数加法公式:a/b + x/y = (a*y + x*b)/(b*y)
            long numerator = a * y + x * b; 
            long denominator = b * y;
            simplified = simplifyFraction(numerator, denominator);
            a = simplified[0];  // 更新累加分子
            b = simplified[1];  // 更新累加分母
        }
        
        // 结果格式化输出
        if (a % b == 0) {                      // 情况1:结果为整数
            System.out.println(a / b);
        } else {
            long integerPart = a / b;          // 提取整数部分
            if (integerPart != 0) {            // 情况2:带分数(如3 1/2)
                System.out.print(integerPart + " ");
                System.out.println((a % b) + "/" + b);
            } else {                           // 情况3:真分数(如2/5)
                System.out.println(a + "/" + b);
            }
        }
    }
    
    // 分数化简(核心方法)
    private static long[] simplifyFraction(long a, long b) {
        long g = gcd(Math.abs(a), Math.abs(b)); // 计算最大公约数
        a /= g;    // 约分分子
        b /= g;    // 约分分母
        // 确保分母为正(数学规范)
        if (b < 0) {
            a *= -1;
            b *= -1;
        }
        return new long[]{a, b};
    }
    
    // 欧几里得算法求最大公约数
    private static long gcd(long a, long b) {
        while (b != 0) {          // 辗转相除
            long temp = b;
            b = a % b;
            a = temp;
        }
        return a;
    }
}


L1-010 比较大小 

  1. 数据读取:读取一行输入,分割为3个整数
  2. 快速排序:使用Arrays.sort()进行升序排列
  3. 定向输出:按最小值->中位数->最大值格式拼接字符串
import java.io.*;
import java.util.*;

public class Main {

    static BufferedReader sc = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
    static String[] ss;  // 输入分割缓存
    static String s;     

    public static void main(String[] args) throws IOException {
        // 读取输入并分割为3个整数
        ss = sc.readLine().split(" ");  // 按空格分割输入
        int[] nums = new int[3];         // 存储三个数字的数组
        
        // 转换字符串为整数
        for(int i=0;i<3;i++) {
            nums[i] = Integer.parseInt(ss[i]);
        }
        
        // 升序排序(时间复杂度O(nlogn))
        Arrays.sort(nums);  
        
        // 格式化输出(严格按"a->b->c"格式)
        out.print(nums[0]+"->");  // 最小值
        out.print(nums[1]+"->");  // 中间值
        out.print(nums[2]);       // 最大值
        out.println();            // 换行符结尾
        

        sc.close();
        out.flush();
        out.close();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值