备赛蓝桥杯的第二弹,自用学习笔记记录
# 2023试题A日期统计(1枚举变量、2枚举范围(缩减运行时间)、3解的检验与统计(去重))尽量提早退出循环(continue等...) """stl 数据库""" # text = [5,6,8,6,9,1,6,1,2,4,9,1,9,8,2,3,6,4,7,7,5,9,5,0,3,8,7,5,8,1,5,8,6,1,8,3,0,3,7,9,2, # 7,0,5,8,8,5,7,0,9,9,1,9,4,4,6,8,6,3,3,8,5,1,6,3,4,6,7,0,7,8,2,7,6,8,9,5,6,5,6,1,4,0,1, # 0,0,9,4,8,0,9,1,2,8,5,0,2,5,3,3] # s = set()#集合去重 # month = [31,28,31,30,31,30,31,31,30,31,30,31] # {}:字典 []:列表 ():集合 # for i in range(93): # if text[i] == 2 and text[i+1] == 0 and text[i+2] == 2 and text[i+3] == 3: # if text[i+4] == 0: # if text[i+5] == 2: # if 0 <= text[i+6] <=2 and text[i+7] <= 9: # s += str(text[i])+str(text[i+1])+str(text[i+2])+str(text[i+3])+str(text[i+4])+str(text[i+5])+str(text[i+6])+str(text[i+7]) # elif text[i+4] == 1 or 3 or 5 or 7 or 8: # if 0 <= text[i+6] <=2: # elif text[i+4] == 1: # pass#过于复杂而且情况有点多 # 题目要求没说必须连着,我这个连着了 arr = [5,6,8,6,9,1,6,1,2,4,9,1,9,8,2,3,6,4,7,7,5,9,5,0,3,8,7,5,8,1,5,8,6,1,8,3,0,3,7,9,2, 7,0,5,8,8,5,7,0,9,9,1,9,4,4,6,8,6,3,3,8,5,1,6,3,4,6,7,0,7,8,2,7,6,8,9,5,6,5,6,1,4,0,1, 0,0,9,4,8,0,9,1,2,8,5,0,2,5,3,3] month = [31,28,31,30,31,30,31,31,30,31,30,31] s = set() month_checked = [0] * 12#创建了一个一行十二个0的列表 for i in range(93): if arr[i] == 2: for j in range(i+1,94): if arr[j] == 0: for k in range(j+1,95): if arr[k] == 2: for l in range(k+1,96): if arr[l] == 3:#年份2023在此完成后面的就是月日 #月份开始 for a in range(l+1,97): if arr[a] < 2:#{0,1} for b in range(a+1,98): month1 = arr[a] * 10 + arr[b] #月份两个数被转成一个数 if 0 < month1 < 13 and month_checked[month1-1] == 0: #month_checked[month1-1] == 0代表这个月份还没有被用过 month_checked[month1-1] = 1 #日期开始 for c in range(b+1,99): if arr[c] < 4:#{0,1,2,3} for d in range(c+1,100): day1 = arr[c] * 10 + arr[d] if 0 < day1 <= month[month1-1]: s.add(arr[a]*1000+arr[b]*100+arr[c]*10+arr[d]) print(len(s)) # 我的是把各个数单独看,不免会有多种复杂情况,如有三十一天时:1开头时有[0,9],3开头时只有[0,1] # 但是如果把两个数合成一个就会简单很多了 # 只是月份的检查有必要么: for i in range(93): if arr[i] == 2: for j in range(i+1, 94): if arr[j] == 0: for k in range(j+1,95): if arr[k] == 2: for l in range(k+1, 96): if arr[l] == 3: # 年份2023在此完成后面的就是月日 # 月份开始 for a in range(l+1, 97): if arr[a] < 2: # {0,1} for b in range(a+1, 98): month1 = arr[a] * 10 + arr[b] # 月份两个数被转成一个数 if 0 < month1 < 13: # 日期开始 for c in range(b+1, 99): if arr[c] < 4: # {0,1,2,3} for d in range(c+1, 100): day1 = arr[c] * 10 + arr[d] if 0 < day1 <= month[month1-1]: s.add(arr[a]*1000+arr[b]*100+arr[c]*10+arr[d]) print(len(s)) # 月份检查与否答案都相同 # 2023 01串的熵 import math # xi = 0 # long = 23333333 # ans = 0 # for i in range(long): # ans += -(p(x) * math.log2(p(x))) # if ans = 11625907.5798: """ c++: #include<bits/stdc++.h> using namespace std; int main(){ int n=23333333; for(int i=0;i<=n;i++){ double x=(-1.0)*i/n*log2(1.0*i/n)*i; double y=(-1.0)*(n-i)/n*log2(1.0*(n-i)/n)*(n-i); if(x+y>=11625907.5798&&x+y<=11625907.5799){ cout<<i; return 0; } } } """ # n = 23333333 # for i in range(n): # if i / n > 0:#注意定义域 # x = (-1) * i / n * math.log2(1*i/n)*i # y = (-1) * (n-i) / n * math.log2(1*(n-i)/n)*(n-i) # if 11625907.5798 <= x+y <= 11625907.5799: # print(i) # 得出两个结果:11027421 和 12305912 # H(s) = - Σ(n,i=1) (p(x) * math.log2(p(x))) # 题目中还有个条件0出现次数比1小 # n = 23333333#长度为23333333的01串 # for i in range(n):#i即0的个数 # if i / n > 0:#即i > 0 i∈[1,n-1] #x是0,y是1 # x = (-1) * (i / n) * math.log2(i/n) * i#*i是权重因子,为了调整熵的大小 # y = (-1) * ((n-i) / n) * math.log2((n-i)/n) * (n-i) # if 11625907.5797 <= x+y <= 11625907.5799 and x<y: # #x和y是变量,他们的和会随着i的变化而变化,这里的范围是在寻找使得x+y落在这个狭窄范围的i值 # #以为默认double,精度会丢失,这里我们认为差值<0.0001就算相等 # print(i) # #正确结果为11027421 # n = 23333333#长度为23333333的01串 # for i in range(n): # if i / n > 0:#即i > 0 i∈[1,n-1] # x = (-1) * (i / n) * math.log2(i/n) * i # y = (-1) * ((n-i) / n) * math.log2((n-i)/n) * (n-i) # if x+y == 11625907.5798 and x<y: # print(i) # #输出结果为空 # 用python试试:H(s) = - Σ(n,i=1) (p(x) * math.log2(p(x))) # n = 23333333 # res = 0 # for i in range(n): # if 0 < i / n < (n-i)/n:######下面这个i是 有i个0 # res = -(i/n) * math.log2(i/n) * i - ((n-i)/n) * math.log2((n-i)/n) * (n-i) #math domain error定义域错误 # if abs(res-11625907.5798) <= 0.0001: # print(i) # 其实还是一个意思 # n代表的是有多少个x,例如01串中就只有两个数:1和0 # 例题中2/3的有两项,相当于- 2/3 log2(2/3) 乘了2 ,即我们后面式子里面的权重因子 # 总结:一定要多读几遍题目,然后看懂例题才能做会 # 进制转换和素数 # 经典模型 最短路径和杨辉三角 欧几里得算法 (最大公约数。最小公倍数) 素数分解 # 最小公倍数: a = 20 b = 30 for i in range(min(a,b), a*b): if i % a == 0 and i % b == 0: print(i) break # 最大公约数: x = 50 y = 60 for i in range(max(x, y)+1, 1, -1): if x % i == 0 and y % i == 0: print(i) break # 动态规划dp[][] # 总结往年例题考的什么 空间转换mb和bite等单位的转化,256mb可以存多少32位二进制 # 第十二届蓝桥杯真题c 直线 初中数学知识 # d 货物摆放 n=l*w*h,给出一个n值求出有多上中方案使得n = 该值(longlong int) """思路一:三重循环暴力分解 思路二:(素数概念)一个东西放在三个篮子 把该数分成多少个素因子,将其放在篮子里有多少种结果 掌握素因子得分解 分解后用高中数学排列组合A和C计算(注意去重)""" # 等差素数列问题 用线性代数把10**6内得素数筛出来(筛素数算法 *背) # 埃式筛法: p.s. 1不是素数 N = 1000000 P = [False] * (N + 1) # 创建了一个包含N+1个False值的列表,并将这个列表赋值给变量P pNum = 0 # 素数的数量 for i in range(2, N): if P[i] is False: pNum += 1 for j in range(i*2, N+1, i): # 步长为i即i的整数倍被排除 P[j] = True print(pNum) # 自己尝试打一遍埃式筛选法: n = 1234 ans = 0 p = [False] * (n + 1) for i in range(2, n+1): if p[i] is False: ans += 1 for j in range(i*2, n+1, i): p[j] = True print(ans) # 对啦!! # 欧拉筛法 N = 1000000 prime = [0] * (664580) # 通过计算知有664579个 p = [False] * (N + 1) pNum = 0 i = 2 while i <= N: if p[i] is False: prime[pNum] = i pNum += 1 j = 0 while (j<pNum and i*prime[j] <= N): p[i*prime[j]] = True if(i % prime[j] == 0): break j += 1 i += 1 print(pNum) # 路径 最小公倍数最大公约数 step1 建图(临阶矩阵就是个二维数组但不全等于,有端点(对称矩阵))(可以用二维数组表达) step2用算法解决 # floyd算法 digit算法 # 时间显示——打卡题 (闰年月) 给一串时间得出其时分秒 # 第八届 日期问题 先排查不可能的比如说13月...... 用枚举思路做,除去不正确的 # 砝码称重 一个天平n个砝码依次不相等,求可以称出多少不同重量(去重) 动态规划(正作用、副作用和无作用) # 2020的九进制转十进制 九进制2022转换成十进制是多少 print(2 * 9**3 + 2 * 9**1 + 2 * 9**0) # 答案1478 # 刷题统计 输入a,b,c (周一到周五每天a题,周六周天每天b题,共c题)问要做多少天 (放大换成一周总共做的题目是相同的) a = 10 b = 15 c = 200 week = c // (a*5+b*2) #整除是只要整数,不论小数部分是否>=0.5都舍去 out = c % 85 # out 得出来是一共剩了多少道题 if out <= 50: if out % 10 == 0: ans = week * 7 + (out//10) print(ans) else: print(week*7 + out//10 + 1) else: if (out-50) % 15 == 0: print(week*7 + 5 + (out-50)%15) else: print(week*7 + 5 + (out-50)%15 + 1) # 试题E X进制减法(最低数为二进制,第二位十进制,第三位八进制,则x进制数321的十进制为65) """ 三个分开的数合成一个数,((a*10)+b)*10...... mod为模 %mod """ # 试题D 修剪灌木 输入a个灌木 从左往右依次修剪,找最高长度 """ 输入格式:一个正整数N 输出格式:输出N行,每行一个整数, """ # 试题F 统计子矩阵 (前缀和:s[7]-s[4-1],求第三个到第七个的数的和(S 数列和)--前n项和) # 二维前缀和:s[i][j] = s[i][j-1] + s[i-1][j] - s[i-1][j-1] + a[i][j] # 差分 差分是前缀和的逆运算(反函数)(从第a项到第b项每个项+c) # 求a的差分b,b是a的前缀和,第x项+c,第y项-c,再求其前缀和得改掉的数组 # 双指针 # 积木画 输入一个n表示画布面积求有多少种拼法(有两种积木) 动态规划找状态方程 # 扫雷 # 李白打酒加强版 # 砍竹子 给x个竹子各自高度h (下取整) 砍最高的,如果几个数字相等且相邻则一起被砍(先砍高的让高的变成矮的一起砍)