第十一届蓝桥杯 2020年国赛真题 (Java 大学A组)


  做套题打发下时间。


#A 合数个数

本题总分: 5 5 5


问题描述

  一个数如果除了 1 1 1 和自己还有其他约数,则称为一个合数。例如: 1 , 2 , 3 1,2,3 1,2,3 不是合数, 4 , 6 4, 6 4,6 是合数。

  请问从 1 1 1 2020 2020 2020 一共有多少个合数。


答案提交

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


1713


埃氏筛


public class Test {
   

    static int N = 2020, ans = 0;

    public static void main(String[] args) {
   
        boolean[] factor = new boolean[N + 1];
        for (int i = 2; i <= N; i++)
            if (!factor[i])
                for (int j = i << 1; j <= N; j += i) factor[j] = true;
            else ans++;
        System.out.println(ans);
    }
}

  无他,签到尔。



#B 含 2 天数

本题总分: 5 5 5


问题描述

  小蓝特别喜欢 2 2 2,今年是公元 2020 2020 2020 年,他特别高兴,因为每天日历上都可以看到 2 2 2

  如果日历中只显示年月日,请问从公元 1900 1900 1900 1 1 1 1 1 1 日到公元 9999 9999 9999 12 12 12 31 31 31 日,一共有多少天日历上包含 2 2 2。即有多少天中年月日的数位中包含数字 2 2 2


答案提交

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


1994240


所以 Java 是世界上最好的语言


import java.time.LocalDate;

public class Test {
   

    static int ans = 0;

    public static void main(String[] args) {
   
        LocalDate start = LocalDate.of(1900, 1, 1);
        LocalDate end = LocalDate.of(9999, 12, 31);
        while (start.compareTo(end) <= 0) {
   
            if (start.toString().contains("2")) ans++;
            start = start.plusDays(1);
        }
        System.out.println(ans);
    }
}

归纳法


  首先答案可以分为两部分,

  一、年份数位中包含数字 2 2 2 的个数。

  二、年份数位中不含数字 2 2 2 的个数。

  两部分分别计算,而对于闰年,因为闰月为 2 2 2 月份,也就是包含闰月的时间一定包含 2 2 2,故我们将 1900 1900 1900 9999 9999 9999 之间所有年份都视为平年,再在答案上累加一个闰年数即可。

  现在来讨论一个平年中,月日部分某数位包含 2 2 2 的情况,我们先将 2 2 2 12 12 12 分离出来,计为 28 + 31 28 + 31 28+31,其余的部分因为 30 30 30 31 31 31 日以及月份都不包含 2 2 2,于是我们将 1 ∼ 9 1 \sim 9 19 日、 10 ∼ 19 10 \sim 19 1019 日、 20 ∼ 29 20 \sim 29 2029 日中包含的 2 2 2 的月份累加为 1 + 1 + 10 1 +1 + 10 11+10,对于一个平年的日月部分,包含有 2 2 2 的个数为 179 179 179

  然后讨论 1900 ∼ 9999 1900 \sim 9999 19009999 中包含有 2 2 2 的年份,对此可以拆分为 100 k ∼ 100 k + 99 100k \sim 100k + 99 100k100k+99 k ∈ [ 19 , 99 ] k \in [19, 99] k[19,99] 的若干个小区间,再从中剔除 k = { [ 20 , 29 ] , 32 , 42 , ⋯   , 92 } k = \{[20,29],32,42,\cdots,92\} k={ [20,29],32,42,,92} 17 17 17 个区间,接下来的区间中,个十位包含 2 2 2 的有 100 k + 2 , 100 k + 12 , 100 k + [ 20 , 29 ] , ⋯   , 100 k + 92 100k + 2, 100k + 12, 100k + [20,29],\cdots,100k + 92 100k+2,100k+12,100k+[20,29],,100k+92 19 19 19 个,综上年份包含 2 2 2 的年份个数为 19 100 ( 9999 − 1900 + 1 − 1700 ) + 1700 = 1216 \frac{19}{100}(9999 - 1900 + 1 - 1700) + 1700 = 1216 10019(99991900+11700)+1700=1216,不包含的则为 9999 − 1900 + 1 − 1216 = 5184 9999 - 1900 + 1 - 1216 = 5184 99991900+11216=5184

  最后就是统计 1900 1900 1900 9999 9999 9999 之间的闰年,根据容斥原理,设 f y e a r f_{year} fyear 1 1 1 y e a r year year 年之间的闰年数,则 f y e a r = ⌊ y e a r 4 ⌋ − ⌊ y e a r 100 ⌋ + ⌊ y e a r 400 ⌋ f_{year} = \lfloor\frac{year}4\rfloor - \lfloor\frac{year}{100}\rfloor + \lfloor\frac{year}{400}\rfloor fyear=4year100year+400year,给定年份之间的闰年数为 f 9999 − f 1899 = 1964 f_{9999} - f_{1899} = 1964 f9999f1899=1964

  综上,答案为 1216 × 365 + 5184 × 179 + 1964 = 1994240 1216 × 365 + 5184 × 179 + 1964 = 1994240 1216×365+5184×179+1964=1994240

  由于网络上不依赖 A P I \mathrm{API} API 实现的程序完成题目所述功能的程序有很多,这里便不再费这个精力去编写了。


#C 本质上升序列

本题总分: 10 10 10


问题描述

  小蓝特别喜欢单调递增的事物。
  在一个字符串中,如果取出若干个字符,将这些字符按照在字符串中的顺序排列后是单调递增的,则成为这个字符串中的一个单调递增子序列。
  例如,在字符串 l a n q i a o \mathrm{lanqiao} lanqiao 中,如果取出字符 n \mathrm{n} n q \mathrm{q} q,则 n q \mathrm{nq} nq 组成一个单调递增子序列。类似的单调递增子序列还有 l n q \mathrm{lnq} lnq i \mathrm{i} i a n o \mathrm{ano} ano 等等。
  小蓝发现,有些子序列虽然位置不同,但是字符序列是一样的,例如取第二个字符和最后一个字符可以取到 a o \mathrm{ao} ao,取最后两个字符也可以取到 a o \mathrm{ao} ao
  小蓝认为他们并没有本质不同。
  对于一个字符串,小蓝想知道,本质不同的递增子序列有多少个?
  例如,对于字符串 l a n q i a o \mathrm{lanqiao} lanqiao,本质不同的递增子序列有 21 21 21 个。它们分别是 l \mathrm{l} l a \mathrm{a} a n \mathrm{n} n q \mathrm{q} q i \mathrm{i} i o \mathrm{o} o l n \mathrm{ln} ln a n \mathrm{an} an l q \mathrm{lq} lq a q \mathrm{aq} aq n q \mathrm{nq} nq a i \mathrm{ai} ai l o \mathrm{lo} lo a o \mathrm{ao} ao n o \mathrm{no} no i o \mathrm{io} io l n q \mathrm{lnq} lnq a n q \mathrm{anq} anq l n o \mathrm{lno} lno a n o \mathrm{ano} ano a i o \mathrm{aio} aio
  请问对于以下字符串(共 200 200 200 个小写英文字母,分四行显示):(如果你把以下文字复制到文本文件中,请务必检查复制的内容是否与文档中的一致。在试题目录下有一个文件 inc.txt,内容与下面的文本相同)

tocyjkdzcieoiodfpbgcncsrjbhmugdnojjddhllnofawllbhf
iadgdcdjstemphmnjihecoapdjjrprrqnhgccevdarufmliqij
gihhfgdcmxvicfauachlifhafpdccfseflcdgjncadfclvfmad
vrnaaahahndsikzssoywakgnfjjaihtniptwoulxbaeqkqhfwl

  本质不同的递增子序列有多少个?


答案提交

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


3616159


动态规划


  首先考虑上升子序列问题,即子串可以相同的情况。

  设 f i f_i fi 为以字符串 S [ 1 , n ] S[1,n] S[1,n] i i i 个字符结尾的最长递增子序列的个数,则总个数为 ∑ i = 1 n f i \sum_{i=1}^nf_i i=1nfi,状态转移方程为 f i = ∑ j = 1 i − 1 f j ( S [ i ] > S [ j ] ) f_i = \sum_{j=1}^{i-1}f_j(S[i] > S[j]) fi=j=1i1fj(S[i]>S[j])

  为了避免出现重复子串,考虑互斥的划分方式,

  有状态 f i , c f_{i,c} fi,c 表示到第 i i i 个字符为止,以 c c c 结尾的本质不同子串的个数为多少,显然答案为 ∑ c f n , c \sum_c f_{n,c} cfn,c

  可是如何保证不重不漏呢?

  对于 c ≠ S [ i ] c \neq S[i] c=S[i],显然有 f i , c = f i − 1 , c f_{i,c} = f_{i - 1, c} fi,c=fi1,c,而对于 c = S [ i ] c = S[i] c=S[i] 的情况,考虑重新统计即 f i , c = ∑ c ′ = 1 c − 1 f i − 1 , c ′ f_{i,c} = \sum_{c'=1}^{c-1}f_{i-1,c'} fi,c=c=1c1fi1,c,不重是做到了,即可不重不漏。

   证明半天证明了一坨屎,其实可以用反证法,但反证太无聊了。

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class Test {
   

    public static void main(String[] args) {
     new Test().run(); }

    void run() {
   
        try(
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值