第十届蓝桥杯大赛软件类决赛 Java大学C组

试题 A: 奇数倍数

【问题描述】
请你找到最小的整数 X 同时满足:
• X 是 2019 的整倍数
• X 的每一位数字都是奇数
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可
本题的结果为一 个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分

【分析】
这题非常简单只需找出2019的倍数数之后,然后逐位判断是否是奇数,注意0也是偶数,有0的也不算
【代码演示】

public class Main {
    public static void main(String[] args) {
         for (int i = 2019; i < 500000; i += 2019) {
            String str = i + "";
            for (int j = 0; j < str.length(); j++) {
                if (Integer.parseInt(str.charAt(j) + "") % 2 == 0) {
                    break;
                }
                if (j==str.length()-1){
                System.out.println(i);
                break;
                }
            }
        }
    }

[答案] 139311

试题 B: 递增序列

【问题描述】
对于一个字母矩阵,我们称矩阵中的一个递增序列是指在矩阵中找到两个
字母,它们在同一行,同一列,或者在同一 45 度的斜线上,这两个字母从左向
右看、或者从上向下看是递增的。
例如,如下矩阵中
LANN
QIAO
有LN、LN、AN、AN、IO、AO、LQ、AI、NO、NO、AQ、IN、AN 等 13 个
递增序列。注意当两个字母是从左下到右上排列时,从左向右看和从上向下看
是不同的顺序。
对于下面的 30 行 50 列的矩阵,请问总共有多少个递增序列?(如果你把
以下文字复制到文本文件中,请务必检查复制的内容是否与文档中的一致。在
试题目录下有一个文件 inc.txt,内容与下面的文本相同)

VLPWJVVNNZSWFGHSFRBCOIJTPYNEURPIGKQGPSXUGNELGRVZAG
SDLLOVGRTWEYZKKXNKIRWGZWXWRHKXFASATDWZAPZRNHTNNGQF
ZGUGXVQDQAEAHOQEADMWWXFBXECKAVIGPTKTTQFWSWPKRPSMGA
BDGMGYHAOPPRRHKYZCMFZEDELCALTBSWNTAODXYVHQNDASUFRL
YVYWQZUTEPFSFXLTZBMBQETXGXFUEBHGMJKBPNIHMYOELYZIKH
ZYZHSLTCGNANNXTUJGBYKUOJMGOGRDPKEUGVHNZJZHDUNRERBU
XFPTZKTPVQPJEMBHNTUBSMIYEGXNWQSBZMHMDRZZMJPZQTCWLR
ZNXOKBITTPSHEXWHZXFLWEMPZTBVNKNYSHCIQRIKQHFRAYWOPG
MHJKFYYBQSDPOVJICWWGGCOZSBGLSOXOFDAADZYEOBKDDTMQPA
VIDPIGELBYMEVQLASLQRUKMXSEWGHRSFVXOMHSJWWXHIBCGVIF
GWRFRFLHAMYWYZOIQODBIHHRIIMWJWJGYPFAHZZWJKRGOISUJC
EKQKKPNEYCBWOQHTYFHHQZRLFNDOVXTWASSQWXKBIVTKTUIASK
PEKNJFIVBKOZUEPPHIWLUBFUDWPIDRJKAZVJKPBRHCRMGNMFWW
CGZAXHXPDELTACGUWBXWNNZNDQYYCIQRJCULIEBQBLLMJEUSZP
RWHHQMBIJWTQPUFNAESPZHAQARNIDUCRYQAZMNVRVZUJOZUDGS
PFGAYBDEECHUXFUZIKAXYDFWJNSAOPJYWUIEJSCORRBVQHCHMR
JNVIPVEMQSHCCAXMWEFSYIGFPIXNIDXOTXTNBCHSHUZGKXFECL
YZBAIIOTWLREPZISBGJLQDALKZUKEQMKLDIPXJEPENEIPWFDLP
HBQKWJFLSEXVILKYPNSWUZLDCRTAYUUPEITQJEITZRQMMAQNLN
DQDJGOWMBFKAIGWEAJOISPFPLULIWVVALLIIHBGEZLGRHRCKGF
LXYPCVPNUKSWCCGXEYTEBAWRLWDWNHHNNNWQNIIBUCGUJYMRYW
CZDKISKUSBPFHVGSAVJBDMNPSDKFRXVVPLVAQUGVUJEXSZFGFQ
IYIJGISUANRAXTGQLAVFMQTICKQAHLEBGHAVOVVPEXIMLFWIYI
ZIIFSOPCMAWCBPKWZBUQPQLGSNIBFADUUJJHPAIUVVNWNWKDZB
HGTEEIISFGIUEUOWXVTPJDVACYQYFQUCXOXOSSMXLZDQESHXKP
FEBZHJAGIFGXSMRDKGONGELOALLSYDVILRWAPXXBPOOSWZNEAS
VJGMAOFLGYIFLJTEKDNIWHJAABCASFMAKIENSYIZZSLRSUIPCJ
BMQGMPDRCPGWKTPLOTAINXZAAJWCPUJHPOUYWNWHZAKCDMZDSR
RRARTVHZYYCEDXJQNQAINQVDJCZCZLCQWQQIKUYMYMOVMNCBVY
ABTCRRUXVGYLZILFLOFYVWFFBZNFWDZOADRDCLIRFKBFBHMAXX

【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一
个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分
【分析】
这题需要使用IO流来读取文件,然后判断每个字符的五个方向是否符合递增序列,为什么是五个方向呢?因为题目中说每两个字符在同一行、同一列、同一45度中,必须是从左往右看、从上往下看是递增的,所以只有右上、右、右下、下、左下,这五个方向,然后用种子搜索算法,寻找每个字符是否符合条件
【代码演示】

import java.io.*;
import java.util.Arrays;
/**
 *
 *  种子搜索算法
 **/
public class Main {
    public static void main(String[] args) throws Exception {
        //记录总数
        int sum = 0;
        //获取文件中所有字符并储存在二维数组中
        char[][] c = new char[30][50];
        int index = 0;
        //IO流读取文件
        BufferedReader buf = new BufferedReader(new FileReader(new File("src/tt.text")));
        String s;
        while ((s = buf.readLine()) != null) {
            c[index++] = s.toCharArray();
        }
        //定义了每个字符的各个方向
        int[][] arr = {{-1, 1}, {1, 0}, {1, 1}, {0, 1}, {1, -1}};
        for (int i = 0; i < 30; i++) {
            for (int j = 0; j < 50; j++) {
                for (int k = 0; k < 5; k++) {
                    int x = i, y = j;
                    while (true) {
                        x += arr[k][0];
                        y += arr[k][1];
                        if (x < 0 || y < 0 || x >= 30 || y >= 50) {
                            break;
                        }
                        if (c[x][y] > c[i][j]) {
                            sum++;
                        }
                    }
                }
            }
        }
        System.out.println(sum);
    }
}

试题 C: 平方拆分

【问题描述】
将 2019 拆分为若干个两两不同的完全平方数之和,一共有多少种不同的方
法?
注意交换顺序视为同一种方法,例如 132 + 252 + 352 = 2019 与 132 + 352 +
252 = 2019 视为同一种方法。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一
个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
【分析】
首先不同数的平方最高到45,因为45^2就大于2019了,所有从1到45中找,使用回溯算法,每次执行方法用2019-m*m(m=i),i为每次增加的1-45的数,然后下次执行方法时,判断2019是否为0,为0就加一次次数,为负数就return
【代码演示】


public class Main {
    /**
     * 将 2019 拆分为若干个两两不同的完全平方数之和,一共有多少种不同的方法?
     * 注意交换顺序视为同一种方法
     * 例如 132 + 252 + 352 = 2019 与 132 + 352 + 252 = 2019 视为同一种方法。
     *
     *  使用回溯算法
     */
    public static void main(String[] args) {
        help(1,45,2019);
        System.out.println(sum);
    }
    static int sum=0;
    public static void help(int i,int j,int k){
        //说明平方和比2019大,就停止
        if (k<0) return;
        //说明平方和正好等于2019
        if (k==0) {
            sum++;
            return;
        }
        for (int m = i; m < j; m++) {
            help(m+1,j,k-m*m);
        }
    }
}

试题 D: 切割

【问题描述】
在 4 × 4 的方格矩阵中画一条直线。则直线穿过的方格集合有多少种不同的
可能?
这个里直线穿过一个方格当且仅当直线将该方格分割成面积都大于 0 的两
部分

试题 E: 序列求和

【问题描述】
学习了约数后,小明对于约数很好奇,他发现,给定一个正整数 t,总是可
以找到含有 t 个约数的整数。小明对于含有 t 个约数的最小数非常感兴趣,并
把它定义为 S t 。
例如 S 1 = 1, S 2 = 2, S 3 = 4, S 4 = 6,· · · 。
现在小明想知道,前 60 个 S i 的和是多少?即 S 1 + S 2 + · · · + S 60 是多少?
【分析】
本题其实不难,就是数目太大,题目中求约数有1-60的数总和,已知100以内的质因数有2,3,5,7,11,13,17…等,然后举个例子,当求约数为10的数的时候,给10分解因数,为2*5,这个数就是2^(5-1) * 3 ^(2-1)=48,按照这个规律可以求出S1到S60的和。规律就是这个数的约数分解因数,然后从大到小分别给质因数当次方-1,最后求每一项的乘积,就是这个数
【代码演示】


import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class Main {
    /**
     * 学习了约数后,小明对于约数很好奇
     * 他发现,给定一个正整数 t,总是可以找到含有 t个约数的整数
     * 小明对于含有 t 个约数的最小数非常感兴趣,并 把它定义为 St
     * 例如 S1 = 1, S2 = 2, S3 = 4, S4 = 6,···。 现在小明想知道
     * 前 60 个 Si 的和是多少?即 S1 + S2 +···+S60 是多少?
     */
    public static void main(String[] args) {
        //寻找有60个约数的最小数,然后求出有1个到60个的约数的和
        long sum = 0;//记录总和
        List<Integer> list = new ArrayList<>();
        for (int i = 2; i <= 100; i++) {
            if (help(i) != 0) {
                list.add(help(i));
            }
        }
        LinkedList<Integer> link = new LinkedList();
        for (int i = 1; i < 61; i++) {
            link = help2(link, i);
            long som = 1;
            for (int j = 0; j < link.size(); j++) {
                som *= Math.pow(list.get(j), link.get(j) - 1);
            }
            link.clear();
            sum += som;
            System.out.println(i + "    " + som);
        }
        System.out.println(sum);
    }

    //分解质因数
    public static int help(int n) {
        for (int i = 2; i < n; i++) {
            if (n % i == 0) return 0;
            if (i == n - 1) return n;
        }
        return n;
    }

    //寻找每个数的约数的因数
    public static LinkedList<Integer> help2(LinkedList<Integer> linkedList, int n) {
        int k = 2;
        while (n > 1) {
            if (n % k == 0) {
                n /= k;
                linkedList.addFirst(k);
            } else k++;
        }
        return linkedList;
    }
}

【答案:292809912969721375】

试题 F: 最长子序列

【问题描述】
我们称一个字符串 S 包含字符串 T 是指 T 是 S 的一个子序列,即可以从
字符串 S 中抽出若干个字符,它们按原来的顺序组合成一个新的字符串与 T 完
全一样。
给定两个字符串 S 和 T,请问 T 中从第一个字符开始最长连续多少个字符
被 S 包含?
【输入格式】
输入两行,每行一个字符串。第一行的字符串为 S,第二行的字符串为 T。
两个字符串均非空而且只包含大写英文字母。
【输出格式】
输出一个整数,表示答案。
【样例输入】
ABCDEABCD
AABZ
【样例输出】
3
【分析】
使用HashMap的key储存S字符串每一位,然后value储存每一位的数量,再循环T的每一位,如果不能从Map里找到该key,就停止,找到之后,value值小于1也停止,如果都符合条件,就cont++
【代码演示】

import java.util.HashMap;
import java.util.Scanner;

public class Main {
    /**
     * 我们称一个字符串 S 包含字符串 T 是指 T 是 S 的一个子序列,
     * 即可以从 字符串 S 中抽出若干个字符,它们按原来的顺序组合成一个新的字符串与 T 完 全一样
     * 给定两个字符串 S 和 T,请问 T 中从第一个字符开始最长连续多少个字符 被 S 包含?
     * 
     * 【输入格式】
     * 输入两行,每行一个字符串。第一行的字符串为 S,第二行的字符串为 T
     * 两个字符串均非空而且只包含大写英文字母。
     * 
     * 【输出格式】
     * 输出一个整数,表示答案。
     * 【样例输入】 ABCDEABCD
     * AABZ
     * 
     * 【样例输出】 3
     */
    public static void main(String[] args) {
        Scanner sr = new Scanner(System.in);
        String S = sr.next();
        String T = sr.next();
        int cont = 0;
        HashMap<Character, Integer> map = new HashMap();
        for (int i = 0; i < S.length(); i++) {
            if (map.get(S.charAt(i)) == null) {
                map.put(S.charAt(i), 1);
                continue;
            }
            map.put(S.charAt(i), map.get(S.charAt(i)) + 1);
        }
        for (int i = 0; i < T.length(); i++) {
            if (map.get(T.charAt(i)) == null) break;
            if (map.get(T.charAt(i)) > 0) {
                cont++;
                map.put(T.charAt(i), map.get(T.charAt(i)) - 1);
            }
        }
        System.out.println(cont);
    }
}

试题 G: 数正方形

【问题描述】
在一个 N × N 的点阵上,取其中 4 个点恰好组成一个正方形的 4 个顶点,
一共有多少种不同的取法?
由于结果可能非常大,你只需要输出模 10^9 + 7 的余数
题目图片

图示
【分析】
如图所示,当正方形为22时,正方形边上只有一个正方形,当为33时,有2个正方形,当为11时,没有;所以当为nn时,一共有11(n-1)+22(n-2)+33(n-3)…nn(n-n),ps:图画的不是特别好,勉强能看吧
【代码演示】

import java.util.Scanner;

public class Main {
    /**
     *  在一个 N ×N 的点阵上,取其中 4 个点恰好组成一个正方形的 4 个顶点,
     *  一共有多少种不同的取法?
     * 由于结果可能非常大,你只需要输出模 10^9 + 7 的余数
     *
     *  【输入格式】
     * 输入包含一个整数 N
     * 【输出格式】
     * 输出一个整数代表答案。
     * 【样例输入】 4
     * 【样例输出】 20
     * 
     *
     */
    public static void main(String[] args) {
        Scanner sr=new Scanner(System.in);
        int n=sr.nextInt();
        final int mod=1000000007;
        long sum=0;
        for (int i = 1; i <n ; i++) {
        //为什么老是要取余mod呢,因为数太大了,每次要多取余几次(dogo)
            sum=(sum+(n-i)*i%mod*i)%mod;
        }
        System.out.println(sum);


    }
}

【输入格式】
输入包含一个整数 N。
【输出格式】
输出一个整数代表答案。
【样例输入】
4
【样例输出】
20

试题 H: 矩阵计数

【问题描述】
一个 N × M 的方格矩阵,每一个方格中包含一个字符 O 或者字符 X。
要求矩阵中不存在连续一行 3 个 X 或者连续一列 3 个 X。
问这样的矩阵一共有多少种?
【输入格式】
输入一行包含两个整数 N 和 M。
【输出格式】
输出一个整数代表答案。
【样例输入】
2 3
【样例输出】
49
【代码演示】

import java.util.Scanner;

public class Main {
    /**
     * 一个 N×M 的方格矩阵,每一个方格中包含一个字符 O 或者字符 X
     * 要求矩阵中不存在连续一行 3 个 X 或者连续一列 3 个 X
     * 问这样的矩阵一共有多少种?
     * 【输入格式】
     * 输入一行包含两个整数 N 和 M。
     * 【输出格式】
     * 输出一个整数代表答案。
     * 【样例输入】 2 3
     * 【样例输出】 49
     */
    public static void main(String[] args) {
        dfs(0, 0);
        System.out.println(cont);
    }

    static Scanner sr = new Scanner(System.in);
    static int n = sr.nextInt();
    static int m = sr.nextInt();
    static int[][] arr = new int[n][m];//0表示O ,1表示X
    static int cont;

    public static void dfs(int i, int j) {
        if (i == n) {
            cont++;
            return;
        }
        if (help(i, j)) {
            arr[i][j] = 1;
            dfs(i + (j + 1) / m, (j + 1) % m);
            arr[i][j] = 0;
        }
        dfs(i + (j + 1) / m, (j + 1) % m);
    }

    public static boolean help(int i, int j) {
        //行数超过2行
        if (i > 1) {
            if (arr[i - 1][j] == arr[i - 2][j] && arr[i - 2][j] == 1) return false;
        }
        //列数超过2行
        if (j > 1) {
            if (arr[i][j - 1] == arr[i][j - 2] && arr[i][j - 2] == 1) return false;
        }
        return true;
    }


}
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Oak Coffee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值