蓝桥杯备战

蓝桥杯备战

资料来源:尚硅谷java数据结构,程序设计竞赛挑战教程(蓝桥杯专题组编写),CSDN优秀博客整理。

第一章 手算题和杂题

1.1 手算题

高斯日记问题

关于日期问题可以善用excel和python的date time库解决
请添加图片描述

请添加图片描述

日期问题

整个20世纪(1901年1月1日至2000年12月31日),一共有多少个星期一?

在Excel中,在A1单元格中输入日期“1901年1月1日”,在B1单元格中输入日期“2000年12月31日”,然后将B1与A1相减得36524天

在这里插入图片描述
然后用36524除以7得出周数,其商为5217,余数为5。再计算1901年1月1日是星期几。在Excel中,右击A1单元格,选择“设置单元格格式”→“数字”→“日期”→“星期三”,单击“确定”,得“星期二”,即1901年1月1日是星期二,如图2.3所示。36524天是5217周多5天,最后5天中没有星期一,说明答案就是5217。也可直接利用Excel的“设置单元格格式”对话框得出2000年12月31日刚好是星期天,从星期三至星期天之间没有星期一,答案也是5217。

from datetime import *
dt1 = datetime(1901,1,1)
dt2 = datetime(2000,12,31)
print(dt1.weekday())  #输出1,表示周二。注意,周一用0表示,周日用6表示
td = dt2- dt1
print(td.days//7)
特殊时间问题

2022年2月22日22: 20是一个很有意义的时间,年份为2022,由3个2和1个0组成,如果将月和日写成4位,为0222,也由3个2和1个0组成,如果将时间中的时和分写成4位,还由3个2和1个0组成。小蓝对这样的时间很感兴趣,他还找到了其他类似的例子,如111年10月11日01: 11、2202年2月22日22: 02等。请问,总共有多少个时间是这种年份写成4位、月日写成4位、时间写成4位后均由3个一种数字和1个另一种数字组成的。注意1111年11月11日11: 11不算,因为它里面没有两种数字。

def check(n):                  #检查数字是否合法,n是排序后的
    if n[0] == n[3]: return False
    if n[1] != n[2]: return False
    if n[0] == n[1] or n[2] == n[3]: return True
    return False

year=[]
for y in range(1,10000):       #0001年~9999年
    s="%04d" %(y)
    s1=sorted(s)
    if check(s1):
        year.append(s1)

day=[]
for m in range(1,13):          #12个月
    for d in range(1,31):      #30日、31日都不符合要求,不用管。同理2月29日、2月30日也不用管
        s="%02d%02d" %(m, d)
        s1=sorted(s)
        if check(s1):
            day.append(s1)


hour=[]
for h in range(0,24):
    for m in range(0,60):
        s="%02d%02d" %(h,m)
        s1=sorted(s)
        if check(s1):
            hour.append(s1)


cnt = 0
for i in year:                #遍历年
    for j in day:             #遍历月日
        for k in hour:        #遍历时分
            if i==j and i==k:
                cnt+=1

print(cnt)   

题目的关键之处在于sorted()函数的使用,让年份,月份,时间的检验有规律可循。

顺子日期

【题目描述】小明特别喜欢顺子。顺子指的就是连续的3个数字:123、456等。顺子日期指的就是在日期的yyyymmdd表示法中,存在任意连续的三位数是一个顺子的日期。例如20220123就是一个顺子日期,因为它包含一个顺子123;而20221023则不是一个顺子日期,它一个顺子也没有。小明想知道在2022年一共有多少个顺子日期。

 1  from datetime import *
 2  dt1 = datetime(2022,1,1)
 3  cnt = 0
 4  for i in range(0,365):
 5      s=%02d%02d%02d” %(dt1.year,dt1.month,dt1.day)    #转换成字符串
 6      dt1 +=  timedelta(days=1)       #timedelta有3种:days、seconds、microseconds
 7      if012in s or123in s or234in s or345in s or   \
 8456in s or678in s or789in s:
 9          cnt +=1
10  print(cnt)
乘积尾零

python中数据类型

string 字符串

int 整数 可以表示很大的整数,不受限制

float 浮点数

给出100个整数5650,4542,3554,……,问它们乘积的末尾有多少个0。

5650 4542 3554 473 946 4114 3871 9073 90 4329 2758 7949 6113 5659 5245 7432 3051 4434 6704 3594 9937 1173 6866 3397 4759 7557 3070 2287 1453 9899 1486 5722 3135 1170 4014 5510 5120 729 2880 9019 2049 698 4582 4346 4427 646 9742 7340 1230 7683 5693 7015 6887 7381 4172 4341 2909 2027 7355 5649 6701 6645 1671 5978 2704 9926 295 3125 3878 6785 2066 4247 4800 1578 6652 4616 1113 6205 3264 2915 3966 5291 2904 1285 2193 1428 2265 8730 9436 7074 689 5510 8243 6114 337 4096 8199 7313 3685 211

data = [5650,4542,3554,473,946,4114,3871,9073,90,4329,
        2758,7949,6113,5659,5245,7432,3051,4434,6704,3594,
        9937,1173,6866,3397,4759,7557,3070,2287,1453,9899,
        1486,5722,3135,1170,4014,5510,5120,729,2880,9019,
        2049,698,4582,4346,4427,646,9742,7340,1230,7683,
        5693,7015,6887,7381,4172,4341,2909,2027,7355,5649,
        6701,6645,1671,5978,2704,9926,295,3125,3878,6785,
        2066,4247,4800,1578,6652,4616,1113,6205,3264,2915,
        3966,5291,2904,1285,2193,1428,2265,8730,9436,7074,
        689,5510,8243,6114,337,4096,8199,7313,3685,211 ]
chengji = 1
for i in data:
    chengji = chengji*i

count=0
chengji = list(str(chengji))
chengji = chengji[::-1]#反转列表
for i in chengji:
    if(i=="0"): count+=1
    else: break

print(count)
 1 num = [5650,4542,3554,473,946,4114,3871,9073,90,4329,
    2758,7949,6113,5659,5245,7432,3051,4434,6704,3594,
    9937,1173,6866,3397,4759,7557,3070,2287,1453,9899,
    1486,5722,3135,1170,4014,5510,5120,729,2880,9019,
    2049,698,4582,4346,4427,646,9742,7340,1230,7683,
    5693,7015,6887,7381,4172,4341,2909,2027,7355,5649,
    6701,6645,1671,5978,2704,9926,295,3125,3878,6785,
    2066,4247,4800,1578,6652,4616,1113,6205,3264,2915,
    3966,5291,2904,1285,2193,1428,2265,8730,9436,7074,
    689,5510,8243,6114,337,4096,8199,7313,3685,211]    #把100个数复制到数组里
 2  s = 1
 3  for i in num:   s=s*i            #直接连乘,结果是一个极大的数
 4  cnt =  0
 5  while s%10 == 0:                 #逐个统计末尾的0的个数
 6         s //= 10                  #除以10,把末尾0去掉
 7         cnt += 1                  #统计0的数量
 8  print(cnt)
相乘

【题目描述】小蓝发现,他将1 至1000000007 之间的不同的数与2021相乘后再求除以1000000007的余数,会得到不同的数。小蓝想知道,能不能在1至1000000007之间找到一个数,其与 2021 相乘后再除以1000000007后的余数为 999999999。如果存在,请在答案中提交这个数;如果不存在,请在答案中提交 0。

 1  for i in range(1,1000000008):
 2      if (i*2021)%1000000007==999999999:
 3          print(i)
 4          break
平方和

【题目描述】小明对数位中含有2、0、1、9的数字很感兴趣,在1到40中这样的数包括1、2、9、10至32、39和40,共28个,它们的和是574,平方和是14362。注意,平方和是指将每个数分别平方后求和的结果。请问,在1到2019中,所有这样的数的平方和是多少?

sum = 0
for i in range(1,2020):
    j = list(str(i))
    if(j.count("0") != 0 or j.count("2")!= 0 or j.count("1")!= 0 or j.count("9")!= 0):
        sum += i**2

print(sum)
sum = 0
for i in range(1,2020):
    j = str(i)
    if("2" in j or "0" in j or "1" in j or "9" in j):
        sum += i**2

print(sum)
卡片拼数

【题目描述】小蓝有很多数字卡片,每张卡片上都是0到9的数字。小蓝准备用这些卡片来拼一些数,他想从1开始拼出正整数,每拼一个,就保存起来,卡片就不能用来拼其他数了。小蓝想知道自己能从1拼到多少。例如,当小蓝有30张卡片,其中0到9各3张,则小蓝可以拼出1到10,但是拼11时卡片1只有一张了,不够拼出11。现在小蓝手里有0到9的卡片各2021张,共20210张,请问小蓝可以从1拼到多少?提示:建议使用计算机编程解决问题。

1、应用excel

先估计可能可以拼出3000多个数。在Excel中输出1~3500,然后检查1用了多少次(搜索有多少个1)、2用了多少次,依次类推,最后发现1用得最多,且1~3181用了2021个1,所以答案是3181。这种方法简单直接

2、python编程

(1)直接编程

num = ['0','1','2','3','4','5','6','7','8','9']*2021
for i in range(1,10000):
    j = list(str(i))
    try:
        for x in j:
            num.remove(x)
    except:
        print(i-1)
        break

(2)数字1用得最多,统计从1开始到哪个数字为止用了2021次数字1即可

 1  s=” “
 2  for i in range(1,100000):
 3       s+=str(i)
 4       if s.count(1) == 2021:
 5            print (i)
 6            break
迷宫

【题目描述】给出一个迷宫,问迷宫内的人有多少能走出来。迷宫的每个位置上有一个人,共100人,每个位置有指示牌,L表示向左走,R表示向右走,U表示向上走,D表示向下走。迷宫地图如下:

请添加图片描述

这道题是典型的DFS算法题,用编程解题至少需要10分钟。因为其是填空题,而且迷宫地图只涉及100个字符,所以可以直接数,从左往右数,从上往下数,约两分钟就能数完。

七段码

题目要求:七段数码管一共有7段可以发光的二极管,分别标记为a、b、c、d、e、f、g,问能表示多少种不同的字符,要求发光的二极管是相连的。

请添加图片描述

当然可以用深度优先搜索或并查集查找连通块解决。

用字符表示数码管不太方便,可以改用数字,a~g分别用1~7表示。这是一个组合问题,从n个数中选r个数有[插图]种组合,例如7选1有7种、7选2有21种、7选5有21种等。

本题统计这些组合中的连续亮灯情况,分为以下7种情况。

亮一个灯:1、2、3、4、5、6、7,共7种。

亮两个灯:12、13、24、25、34、36、45、46、57、67,共10种。

亮3个灯:123、124、125、134、136、234、245、246、257、345、346、367、456、457、467、567,共16种。

亮4个灯,这时不要直接数4个灯,这种情况与灭3个灯是等价的,数3个灯比数4个灯简单。注意灭3个灯后其他的4个亮灯连续的情况:灭123、124、125、126、127、134、135、136、137、157、167、245、257、267、346、357、367、457、467、567,共20种。

亮5个灯,数灭两个灯的情况:灭12、13、14等,共19种。

亮6个灯,数灭一个灯的情况,共7种。

亮7个灯,共1种。对以上所有情况求和,答案是80。

山型数字

【题目描述】这天小明正在学数数。他突然发现有些正整数的形状像一座“山”,如123565321、145541,它们左右对称(回文)且数位上的数字先单调不减,后单调不增。小明数了很久也没有数完,他想让你告诉他在[2022, 2022222022]中有多少个数的形状像一座“山”。

ans = 0
#回文数字的长度是偶数,右边相当于左边的镜面对称
for  i in range(20,20222):
    j = str(i)
    flag = 1
    for i in range(0,len(j)-1):
        if j[i]>j[i+1]:
            flag = 0
            break
    if flag==1:
        ans += 1

#回文数字长度是奇数时,中间的数字可以选比紧挨着的数字大的任意数字,其他数字类似镜面对称
for  i in range(11,10000):
    j = str(i)
    flag = 1
    for i in range(0,len(j)-1):
        if j[i]>j[i+1]:
            flag = 0
            break
    if flag==1:
        ans += 10 - int(j[i+1])
        #这里的原因是数字长度为奇数时,中间的数字可以选比紧挨着的数字大的任意数字 如11211,11311
print(ans)
三角回文数

【题目描述】对于正整数n,如果存在正整数k使得n = 1 + 2 + 3 + … + k =k(k+1)/2,则n称为三角数。例如,66066是一个三角数,因为66066 = 1 + 2 +3 + … + 363。如果一个整数从左到右读出所有数位上的数字,与从右到左读出所有数位上的数字是一样的,则称这个数为回文数。例如,66066是一个回文数,8778也是一个回文数。如果一个整数n既是三角数又是回文数,则称它为三角回文数。例如66066是三角回文数。请问,第一个大于20220514的三角回文数是多少?

for i in range(4000,20000):
    s  = i*(i+1)//2
    if (str(s) == str(s)[::-1]):
        print(s)
        break
#该算法效率太低下,运行不出来
for i in range(20220514,100000000):
    s = str(i)
    flag = 1
    if (s!=s[::-1]):
        flag = 0
    # print(int(i**0.5))
    if ((int(i**0.5)*(int(i**0.5)+1))!= 2*i):
        flag = 0

    if(flag==1):
        print(i)
        break
特殊日期问题

记一个日期为 yy 年 mm 月 dd 日,统计从 2000 年 1月1日(含)到2000000 年 1月 1日(含),有多少个日期满足年份 y 是月份 mm 的倍数,同时也是 dd 的倍数。
当年份是 4 的倍数而不是 100 的倍数或者年份是 400 的倍数时,这一年是国年,其他的年份都不是闺年。

num = [[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31],
       
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28],
        [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31],
        [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30],
        [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31],
        [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30],
        [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31],
        [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31],
        [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30],
        [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31],
        [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30],
        [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]
       ]
ans = 0
for i in range(2000, 2000000):
    if (i % 4 == 0 and i % 100 != 0) or i % 400 == 0:
        if i % 29 == 0:
            ans += 1

    for j in range(1, 13):
        if i % j == 0:
            for z in num[j-1]:
                if i % z == 0:
                    ans += 1

print(ans+1)

注意:思考break的条件一定要想清楚

import java.util.*;
public class Main {
    static int pre[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
    public static void main(String[] args) {
        int sum=0;
        //i是年,j是月,k是日
        for(int i=2000;i<=2000000;i++){
            for(int j=1;j<=12;j++){
                int r=pre[j];
                if(j==2 && (i%400==0 || (i%100!=0 && i%4==0))) r++;
                //2月的闰年是29天
                for(int k=1;k<=r;k++){
                    if(i%j==0 && i%k==0) sum++;
                    if(i==2000000) {        //2000000年1月1号过后,直接跳出
                        i=2000001;
                        j=13;
                        break;
                    }
                }
            }
        }
        System.out.println(sum);
    }
}
num1 = [0,31,28,31,30,31,30,31,31,30,31,30,31]
ans = 0
for i in range(2000, 2000000):
    if (i % 4 == 0 and i % 100 != 0) or i % 400 == 0:
        if i % 29 == 0:
            ans += 1

    for j in range(1, 13):
        if i % j == 0:
            for z in range(1, num1[j] + 1):
                if i % z==0: ans+=1

print(ans+1)
阶乘求和

[问题描述]
令 S = 1! + 2! + 3! +…+ 202320232023!,求 S 的末尾9 位数字
提示: 答案首位不为 0。

#加上前两行代码可使输出的数字位数不受限于4300位
import sys
sys.set_int_max_str_digits(0)

res = 1
sum = 0
for i in range(1,40):
    res *= i
    sum += res

sum = str(sum)
print(sum[len(sum)-9:len(sum):1])#注意分割时,取前不取后。

本题中发现问题,数字过大时要记得找规律,像本题中从40开始以后,阶乘和的最后9位保持不变。

填空题部分结束啦,大家记得在蓝桥练习系统上刷题哦。下次见

  • 31
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值