小白学习笔记2

这篇文章分享了在准备蓝桥杯比赛时的学习笔记,涉及数据处理(如日期统计和字符串压缩),算法优化(如尽早退出循环和连续数的处理),以及动态规划(如素数分解、积木拼法和求和问题)。作者还讨论了字符串的熵计算和进制转换问题,展示了如何利用Python和C++进行相关计算。
摘要由CSDN通过智能技术生成

备赛蓝桥杯的第二弹,自用学习笔记记录

# 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 (下取整) 砍最高的,如果几个数字相等且相邻则一起被砍(先砍高的让高的变成矮的一起砍)
  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值