2024.2.12
**杂题**
1.分数表示
from fractions import Fraction
sum = 0
for i in range(20):
sum += Fraction(1/(2**i))
i+=1
print(sum)
库函数fractions的Fraction
2.日期问题
from datetime import*
a=0 #用于累加计数
start=date(1901,1,1)
end=date(2000,12,31)
while start<=end:
if start.weekday()==0:
a+=1
start+=timedelta(days=1)
print(a)
datetime模块
3.顺子日期
res = 0
for i in range(1, 13):
for j in range(1, 32):
s = "2022%02d%02d" % (i, j)
if "012" in s or "123" in s:
res += 1
print(res)
# 腊月是十二月
占位符
#整数占位符
>>> a = "好好%d好" % (100)
>>> print(a)
好好100好
#%4d 占4位,原字符串默认居右
>>> a = "好好%4d好" % (100)
>>> print(a)
好好 100好
#%-4d 占4位,原字符串默认居左
>>> c = "好好%-4d好" % (100)
>>> print(c)
好好100 好
#%04d 占4位,0补位
>>> d = "好好%04d好" % (100)
>>> print(d)
好好0100好
2024.2.13
4.修剪灌木
N = int(input("请输入灌木的数量:"))
for i in range(N):
l_d = i # 距离最左端点的距离
r_d = N - 1 - i # 距离最右端点的距离
max_height = 2 * max(l_d, r_d) # 最大高度为距离两端点的距离的两倍
print(max_height)
5.最少砝码
import os
import sys
# 请在此输入您的代码
N =int(input())
w=1
num=1
while w<N:
w=w*3+1
num+=1
print(num)
解析:
结果应该是最少的砝码数量
首先,如果要称的重量为1的话,只能选择重量为1的砝码,1是必选的一个砝码。
然后再称比1重的,反正都是要再加砝码,那我们为何不选一个能称的重量尽可能大的呢。
选1、2的砝码可以满足1=1,2=2,1+2=3
选1、3的砝码可以满足1=1,2=3-1,3=3,4=3+1
选1、4的砝码可以满足1=1,2=?无法称2,不合题意
因此我们选择的砝码组合是1、3,此时我们可以称的最大重量为4
当我们还需要再增加砝码时
同理可得
选1、3、9的组合可以满足小于等于13(13=1+3+9)的所有重量
比如说我定义的砝码是1 3 9 3n
1砝码的最大重量值 1
2砝码的最大重量值 4
3 131个砝码最大称到1
2个砝码最大称到43个砝码最大称到13
推出公式为:新一级的砝码最大称重=上一级砝码上限 × 3 + 1
2024.2.14
6.成绩分析
代码学习max min;小数点表示
n=int(input())
lis=list()
for i in range(n):
lis.append(int(input()))
print(max(lis))
print(min(lis))
print("{:.2f}".format(sum(lis)/n))
input函数 输入多个值
7.合法日期
代码注意同时需要y的范围,否则通过率只有80%/(ㄒoㄒ)/~~
代码学习,datetime模块运用
import os
import sys
# 请在此输入您的代码
import datetime
m=int(input())
d=int(input())
try:
a=datetime.date(2021,m,d)
print('yes')
except:
print('no')
技巧
day = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
m, d = int(input()), int(input())
print('yes' if m <= 12 and d <= day[m] else 'no')
8.扫雷
创建a行b列空列表
my_list = [[None] * b for _ in range(a)]
若是直接列出出来后续会出现报错(后续题目出现的问题)
法二:创建嵌套列表
边界处理
多维列表的行数设定
9.标题统计
input函数--未指定输入字符数量
转义字符
此题无要求
extend()
extend()可添加一个可迭代对象
isinstance法
title=input()
a=0
b=0
for i in title:
if isinstance(i,str):
a+=1
if isinstance(i,int):
a+=1
if i==" ":
b+=1
print(a-b)
10.求和
多位数分割
字符串认识
sum=0
for i in range(1,2020):
if '2' in str(i) or '0' in str(i) or '1' in str(i) or '9' in str(i):
sum+=i
print(sum)
11.天数
import calendar
m = int(input())
print(calendar.monthrange(2021,m)[1])
calendar模块
Python calendar模块的常用有趣用法_使用calendar库输出2023年1-12月的日历,要求将星期天设置为星期的第一天-CSDN博客
2024.2.16
12.最大间隙
列表添加元素append
列表排序
13.金币
学习逻辑,原本想整不等式但是不会,多次报错。得到就是成功安装了一个新模块
k=int(input())
i=1
N=0
while k>=i:
k-=i
N+=i*i
i+=1
if k!=0:
N+=k*i
print(N)
法二:最后一行lst[:k]为切片操作
import os
import sys
# 请在此输入您的代码
k = int(input())
lst = []
lst.append(1)
start = 1
for i in range(1, k+1):
for j in range(1, i+2):
lst.append(i+1)
print(sum(lst[:k]))
14.天干地支
输入结果无空格
或
15.特殊日期
法一:调用库
import os
import sys
# 请在此输入您的代码
'''from datetime import *
s = datetime(1900, 1, 1)
e = datetime(9999, 12, 31)
t = timedelta(days=1)
summ = 0
while s < e:
y = int(s.year)
m = int(s.month)
d = int(s.day)
n = y//1000 + ((y//10) % 10) + y % 10 + ((y//100) % 10)
m = m % 10 + m//10 + d % 10 + d//10
if m == n:
summ += 1
s += t
print(summ)'''
print(70910)
法二:逻辑(感觉有点难
import os
import sys
# 请在此输入您的代码
def isLeap(x): # 判断是否为闰年
if (x % 4 == 0 and x % 100 != 0) or x % 400 == 0:
return True
return False
def numAdd(x): # 计算年份个数位的数字和
sums = 0
while x:
sums += x % 10
x //= 10
return sums
start, end = 1900, 9999
ans = 0
day = [1, -2, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1] # 每个月天数和30天的差值
data = []
hstable = dict() # key:月份1~12,value:每个月份月份数位和+日的数位和的区间,如1月份为(2, 32)
for j in range(1,32): # 计算日数位和
data.append(numAdd(j))
for i in range(1, 13): # 初始化哈希表
t = numAdd(i) # 月数位和
for j in range(day[i - 1] + 30): # 遍历一个月的每一天将月数位和加上日数位和
addt = t + data[j]
if addt not in hstable:
hstable[addt] = 1
else:
hstable[addt] += 1 # 哈希表中对应的天数加一
for i in range(start, end + 1): # 遍历每一年
yearsum = numAdd(i) # 计算年的数位和
if yearsum in hstable: # 若年的数位和在哈希表中存在则答案加上对应的天数
ans += hstable[yearsum]
if isLeap(i) and yearsum == 13: # 闰年2月份多一天,位数和为13
ans += 1
print(ans)
16.最大距离
多重列表找最大值
或者
2024.2.18
17.最长递增
import os
import sys
n = int(input())
ls = [*map(int,input().split())]
countmax = 1
count = 1
for i in range(len(ls)-1):
if ls[i] < ls[i+1]:
count += 1
else:
count = 1
countmax = max(countmax,count)
print(countmax)
分析(倒数第二):每次更新 count
的值之后,代码都会通过 max()
函数来比较 count
和 countmax
,并将较大的值赋给 countmax
。这样做的目的是确保 countmax
存储的始终是目前为止出现过的最大连续递增数字的长度
2024.2.19
18.串的处理
.isdigit()可用于判断字符中每个小字是否为数字
.capitalize()为一个字符的第一个字大写区别于.title
#自己+gpt
m = input().split()
c = []
temp1 = []
for word1 in m:
if word1[0].isalpha():
temp1.append(word1.capitalize())
else:
temp1.append(word1)
for word in temp1:
temp = []
i = 0
while i < len(word):
if word[i].isdigit():
if i != 0 and not word[i-1].isdigit() :
temp.append('_')
temp.append(word[i])
if i != len(word) - 1 and not word[i+1].isdigit():
temp.append('_')
else:
temp.append(word[i])
i += 1
c.append(''.join(temp))
f = ' '.join(c)
print(f)
#相似方法的简单处理
s = input().split()
l_new = []
for i in s:
i = list(i)
new=""
for j in range(len(i)-1):
new+=i[j]
if i[j].isdigit() and i[j+1].isalpha():new+='_'
if i[j].isalpha() and i[j+1].isdigit():new+='_'
new+=i[-1]
l_new.append(new)
s_new = " ".join([i[0].upper()+i[1:] for i in l_new])
print(s_new)
re模块
import re
_str = input()
def to_upper(matchd):
return matchd.group(0).upper()
_str = re.sub(r'\b([a-z])', to_upper, _str)
_str = re.sub(r'\b\s{2,}\b', ' ', _str)
_str = re.sub(r'([a-zA-Z])(\d)', r'\1_\2', _str)
_str = re.sub(r'(\d)([a-zA-Z])', r'\1_\2', _str)
print(_str)
19.幸运数字
二、八、十六进制位数和
#十六进制位数和
def num_count_hex(mm):
# 将输入的十进制数转换为十六进制字符串
hex_str = hex(mm)
# 初始化数字和
total = 0
# 遍历十六进制字符串中的每个字符
for char in hex_str:
# 如果字符是 0-9 或 A-F(或 a-f)之间的有效字符,则将其转换为对应的十进制数并加到总和中
if char.isdigit():
total += int(char)
elif char.lower() in ['a', 'b', 'c', 'd', 'e', 'f']:
total += int(char, 16) # 使用 int 函数将十六进制字符转换为对应的十进制数并加到总和中
return total
#关于十六进制位数和的简单处理
sixteen = hex(i)[2:] #取对应十六进制的数
lst1 = []
for j in sixteen:
lst1.append(int(j,16))
sum(lst1)
#二进制位数和
def num_count_bin(mm):
sum = 0
bin_str = []
bin_str = str(bin(mm)[2:])
for mm in range(len(bin_str)):
sum += int(bin_str[mm])
return sum
#八进制位数和
def num_count_oct(mm):
sum = 0
oct_str = []
oct_str = str(oct(mm)[2:])
for mm in range(len(oct_str)):
sum += int(oct_str[mm])
return sum
20.缩位求和
不定数据的位数和简介求法
n=int(input())
while len(str(n))!=1:
x=sum(list(map(int,str(n))))
n=x
print(x)
2024.2.21
21.2023
2023省赛填空1
运行速度慢,约2min,答案无误
import os
import sys
# 请在此输入您的代码
k = 0
for num in range(12345678,98765433):
str1 = ["2","0","2","3"]
for x in str(num) :
if x in str1:
if str1[0] == x:
str1.pop(0)
if len(str1) != 0:
k+=1
print(k)
22.硬币兑换
暴力,for循环暴力所有枚举结果
import os
import sys
arr=[]
for i in range(0,4047):
arr.insert(i,0)
for i in range(1,2024):
for j in range(i+1,2024):
arr[i+j]+=i
print(max(arr))
2024.2.23
23.小蓝做实验
f = open("primes.txt")
m = []
for each in f:
m.append(int(each))
count = 0
for i in m:
for j in range(2,int(i**0.5)+1):
if i % j == 0:
break
else:
count += 1
print(count)
#效率很低,自己的
质数的计算
count = 0
for i in m:
for j in range(2,int(i**0.5)+1):
if i % j == 0:
break
else:
count += 1
第二个循环中,用开方可以减少循环次数
埃氏筛求质数
python 高效求解质数-- 埃氏筛法_python质数筛法-CSDN博客
24.排列字母
字母排序
a=list('WHERETHEREISAWILLTHEREISAWAY')
a.sort()
for i in a:
print(i,end="")
25.寻找整数
L=[]
for i in range(187,10**12,187):
if i%44==33 and i%45==29 and i%46==15 and i%47==5 and i%48==41 and i%49==46:
L.append(i)
if len(L)>=2:
break
step=L[1]-L[0]
flag=0
for i in range(L[0],10**17,step):
if i%20==9 and i%25==9 and i%26==23 and i%27==20 and i%28==25 and i%29==16 and i%30==29 and i%31==27 and i%32==25 and i%33==11 and i%34==17 and i%35==4 and i%36==29 and i%37==22 and i%38==37 and i%39==23 and i%40==9 and i%41==1 and i%42==11 and i%43==11 :
print(i)
break
//好像还可以运用math模块--中国剩余定理,需要数论的相关知识 放个flag先跳过
26.直线
#直线
points=[[x,y] for x in range(20) for y in range(21)] #创建二维列表:代表xy坐标系
docker=set() #创建集合属性的容器:因为集合里的元素不会重复
for i in points: #二重循环遍历每个坐标
x1,y1=i[0],i[1] #注意书写格式:a,b=c,d
for j in points:
x2,y2=j[0],j[1]
if x1==x2: #特殊情况:直线垂直时斜率不存在,先跳过最后计算
continue
k=(y2-y1)/(x2-x1) #斜率公式
b=(x2*y1-x1*y2)/(x2-x1) #截距公式
if (k,b) not in docker: #存入容器里没有的(斜率,截距)对
docker.add((k,b))
print(len(docker)+20) #输出结果:容器的长度40237+斜率不存在的20种情况=40257
27.货物摆放
因素+背包
//逻辑性好强,甘拜下风... 自己的暴力循环严重超时
import os
import sys
# 因素+背包(求因子)+遍历
# 不到50毫秒!!!!!!!!!!
# 请在此输入您的代码
n=2021041820210418
l=[] # !!!!用于存因数不是因子例如:10=2*5
i=2
x=n
while i<pow(x+1,0.5):
if x%i==0:
l.append(i)
x=x//i
else:
i+=1
l.append(x)
s=set() # !!!!用于存因子 如10=1*2*5*10
s.add(1)
for j in l:
p=set()
for k in s:
p.add(j*k)
for k in p:
s.add(k)
count=0
for k1 in s: # 遍历两层求解
for k2 in s:
if n%(k1*k2)==0:
count+=1
print(count)
法二:运行可能超时,答案无误
ans = 0
n = 2021041820210418
lst = []
for i in range(1,int(n**0.5)+1):
if (n % i == 0):
lst.append(i)
if n / i != i:
lst.append(n/i)
for i in lst:
for j in lst:
for k in lst:
if (i*j*k == n):
ans += 1
print(ans)
背包问题
//放个flag
28.路径
此题求的是从结点一,到结点x,到结点y......最终到结点2021路途的最小值。为最小值累加
import os
import sys
import math
# 请在此输入您的代码
# 求最大公约数用辗转相除法(欧几里得算法)
def gcd(a,b):
if b==0:
return a
return gcd(b,a%b)
def gbs(a,b): #求最小公倍数
return a*b//(gcd(a,b))
lst = [float('inf')]*(2021+1)
lst[1] = 0 # 节点从1开始
for i in range(1, 2022): # 节点从1开始
for j in range(i + 1, i + 22):
if j > 2021: # 跳出循环
break
lst[j] = min(lst[j], lst[i] + gbs(i, j))
print(lst[2021])
最大公倍数
要计算两个数的最小公倍数(LCM),可以利用它们的最大公约数(GCD)来求解。最小公倍数等于两个数的乘积除以它们的最大公约数。
def gcd(a, b):
while b:
a, b = b, a % b
return a
def lcm(a, b):
return abs(a * b) // gcd(a, b)
num1 = 2021
num2 = 2022
lcm_result = lcm(num1, num2)
print("最小公倍数:", lcm_result)
1.路径之谜 - 蓝桥云课 (lanqiao.cn) //flag 找题时看到的,国赛困难版,DFS还没学...
2024.2.24
*29.回路计数
第11届蓝桥杯软件类历年真题官方题解——回路计数_哔哩哔哩_bilibili
# ------------1462-回路计数---------
# 题目:从1号教学楼开始,访问完每一栋教学楼一次,又回到一号教学楼的不同方案
# 1.状态压缩+DP
# 每一栋教学楼分为访问和不访问,可以用0,1表示
# 访问完所有的教学楼就用21个1表示。
# 2.动态规划:划分子问题
# 原问题:访问玩每栋教学楼又回到一号楼的不同方案
# 所有的楼都可以回到1号教学楼,因为1和所有都互质
# 最后一次可以在2-21号楼
# 在这基础上,再次划分子问题
# 如果最后一次访问的是2号楼,它可以由上一次所在的教学楼方案数之和得到
# 3.状态转移方程
# dp[i][j] += dp[i-(1//j)][k]
# k一定要在状态i中,并且k和j要有通路,j是最后访问的
# 4.初始状态
# dp[1][0] = 1,只访问1号楼,且当前所在教学楼为1的方案,只有一种
import math
n = 21
state = 1<<21
# 存放教学楼之间是否有路径
Map = [[0]*(n+1) for i in range(n+1)]
dp = [[0]*n for i in range(stat