第十五届蓝桥杯大赛软件赛国赛Java 大学 A 组

汉字田

问题描述

在中国传统文化中,汉字“田”具有非常重要的地位。其最初的象形意义展现了一块被四等分的农田,四个等分代表农田的不同区域,中间交叉点则代表了田间的道路或水渠。在古代,农田的划分与耕作是社会经济的根基,所以“田”字不仅代表农田,还象征着土地、财产和生产力。到了现代,虽“田”字的直接象形意义已经不再明显,但它仍是生活中不可或缺的一部分,在语言文字以及数学逻辑思维训练中都发挥着作用。比如在几何问题中,“田字格”常常被用来帮助理解空间问题。

现在,若将汉字“田”抽象为一个由 9 个点组成的图形,这些点分布在田字格的四个角、四条外边的中点以及田字格的中心。那么请问,一共有多少条直线恰好只经过这 9 个点中的任意两个点?

图片描述

分析: 建议直接画,手做

import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        System.out.println(12);
        scan.close();
    }
}

 空间传送装置

问题描述

蓝桥王国拥有 42座城市以及 42 位骑士。这些骑士按照 1 到 42 的编号顺序,分别居住在对应编号的城市中。即第 1 位骑士居住在城市 1,第 2 位骑士居住在城市 2,依此类推。

最近,王国中引入了一项革命性技术:空间传送装置。该装置可以根据一个长度为 42 的数字排列 a,将所有骑士一次性传送至新的城市。

排列 a 必须由 1∼42 共 4242 个数字组成,且每个数字只出现一次。在传送操作中,位于城市 ii(i=1,2,3,…,42) 的骑士会被传送到城市 ai​。例如,如果 a1​ 的值为 3,那么当前位于城市 1 的骑士会被传送至城市 3。

为测试技术的可靠性,王国决定连续 2024 天每天使用同一排列 a 进行一次传送操作。

小蓝负责为这次测试设计排列 a,她的目标是确保所有骑士在经过 2024 天传送后,都能返回自己的起始城市。而在此之前的任何一天,骑士们不会全部都回到起始城市。

请问,有多少种不同的数字排列 a 能满足小蓝的需求?由于答案可能很大,因此你只需要将答案对 109+7 取模后提交即可

注意事项

  • 数字排列 a 是由 1 到 42 这 42 个数字按照一定顺序排列而成的序列。每个数字在排列中只能出现一次,且所有数字必须全部包含在排列中。

  • 如果两个排列中至少有一个位置上的数字不同,则这两个排列被视为不同的数字排列。例如,{1,2,3,…,42}和 {1,3,2,...,42} 就是不同的数字排列,因为它们在第二个位置上的数不相同。

答案提交

这是一道结果填空题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

分析:

  • 一个排列的是最小的正整数 kk,使得排列重复应用 kk 次后,所有元素回到原位。

  • 数学上,排列的阶等于其循环分解中各循环长度的最小公倍数(LCM)

  • 我们需要计算所有满足上述循环长度条件的排列数。数学上可以表示为:

    总数=42!/8×11×23

    为什么?

  • 总排列数是 42!42!。

  • 但必须强制包含至少一个8、11、23的循环,相当于从总排列中"扣除"这些循环的约束。

  • 除以 8×11×238×11×23 是对这些约束的数学表达。

    import java.util.Scanner;
    // 1:无需package
    // 2: 类名必须Main, 不可修改
    
    public class Main {
      
        // 定义模数 10^9 + 7
        private static final long MOD = 1000000007L;
        
        public static void main(String[] args) {
            Scanner scan = new Scanner(System.in);
            
            // 计算42的阶乘 mod MOD
            long fact = 1;  // 初始化阶乘为1(1! = 1)
            // 从2乘到42(因为1!已经是1,直接从2开始)
            for (int i = 2; i <= 42; i++) {
                fact = fact * i % MOD;  // 每次乘法后取模防止溢出
            }
    
            // 计算分母的逆元:1/(8*11*23) mod MOD
            // 因为题目要求的是42!/(8*11*23) mod MOD
            long denominator = 8 * 11 * 23;  // 计算分母 = 2024
            // 使用费马小定理求逆元:a^(MOD-2) ≡ a^(-1) mod MOD
            long invDenominator = powMod(denominator, MOD - 2, MOD);
    
            // 最终结果 = (42! mod MOD) * (1/2024 mod MOD) mod MOD
            long result = fact * invDenominator % MOD;
    
            // 输出结果
            System.out.println(result);
            scan.close();
        }
        
        /**
         * 快速幂算法计算 a^b mod mod
         * @param a 底数
         * @param b 指数
         * @param mod 模数
         * @return a^b mod mod
         */
        public static long powMod(long a, long b, long mod) {
            long result = 1;  // 初始化结果为1
            while (b > 0) {  // 当指数b还有位时
                if ((b & 1) != 0) {  // 如果当前最低位是1
                    result = result * a % mod;  // 乘以当前的a
                }
                a = a * a % mod;  // a平方
                b >>= 1;  // b右移一位(相当于除以2)
            }
            return result;
        }
    }

    另外解释模逆元的概念:

 进制判断

问题描述

小蓝有 n 个数,他将这 n 个数分别转换成了 2,4,8,16进制之一的形式。 其中 16 进制用大写字母 A 至 F 表示大于等于 10 的数位。

小蓝现在有这 n 个数转换后的结果 Ai​,但他不记得具体每个数转换后是几进制了,他现在只知道转换后的 Ai​ 以及其原本应该小于等于某个数 Bi (10 进制表示) 。

请你帮他找出每个数原本在 10 进制下的值,如果不存在唯一结果请输出 −1。

输入格式

输入的第一行包含一个整数 n。

接下来 n 行,每行包含两个整数 Ai,Bi,用一个空格分隔,其中 AiAi​ 是 2,4,8,16 进制中的一种,Bi​ 是十进制。

输出格式

输出 n 行,每行包含一个整数表示答案。

分析:这个就有点凑巧了,刚好直接使用int value = Integer.parseInt(ai, base); 的作用将字符串 ai 按照进制 base 转换为十进制整数 value。再用try-catch解决报错

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        scanner.nextLine(); // consume the remaining newline
        
        for (int i = 0; i < n; i++) {
            String[] parts = scanner.nextLine().split(" ");
            String ai = parts[0];
            int bi = Integer.parseInt(parts[1]);
            
            List<Integer> validValues = new ArrayList<>();
            int[] bases = {2, 4, 8, 16};
            
            for (int base : bases) {
                try {
                    int value = Integer.parseInt(ai, base);
                    if (value <= bi) {
                        validValues.add(value);
                    }
                } catch (NumberFormatException e) {
                    // The number is not valid for this base, skip
                }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值