1.数论:
基础知识补充:
约数:又称因数,a除以整数b(b≠0) 除得的商正好是整数而没有余数,就是a能被b整除,或b能整除a。a称为b的倍数,b称为a的约数。约数是有限的,一般用最大公约数。所有数都有约数1,和数字本身。
蓝桥1208
import os
import sys
import math
# 请在此输入您的代码
def check(x):
for i in range(2, int(math.sqrt(x)) + 1): # 寻找因子
if x % i == 0: # 能在这个范围内有数整除x说明是合数,否则为质数
return True
return False
ans = 0
for i in range(1, 2021):
if check(i):
ans += 1
print(ans)
蓝桥3205
def get_prime(n):
vis = [0] * (n + 1) # 用来标记质数下标的,0是质数,1是非质数。
vis[0] = vis[1] = 1 # 初始化,大于1的才算质数
prime = [] # 记录质数
for i in range(2, n + 1): # 遍历
if vis[i] == 0: # 如果是质数
prime.append(i) # 添加至质数列表
for j in range(i + i, n + 1, i): # 将其倍数下标记为1
vis[j] = 1
return vis, prime # 返回指数列表和下标
n = int(input())
ans = 0
vis, prime = get_prime(n)
for i in range(len(prime)):
for j in range(i + 1, len(prime)): # 遍历质数下标,如果两个质数下标的差的下标是0,符合要求。
if vis[prime[j] - prime[i]] == 0:
ans += 1
print(ans)
蓝桥3334
import os
import sys
# 请在此输入您的代码
def is_prime(x): # 判断质数的函数
if x <= 1:
return False
m = int(x ** 0.5)
for i in range(2, m + 1):
if x % i == 0:
return False
return True
n = int(input())
ans = 0
for i in range(1, n + 1):
x = i
cnt = 0 # 记录各个数位相加的结果
while x != 0:
cnt += x % 10
x //= 10
if is_prime(cnt): # 如果数位相加是质数的话,符合题意。
ans += 1
print(ans)
蓝桥1463
这题可以直接想到暴力枚举每个L,W,H,然后判断三个值相乘是否等于n,但是直接这样枚举的时间复杂度太高,因为n是16位数,所以我们需要减少一些不必要的计算,一个数只能由它的因子相乘得到,所以我们先把其的因子求出,用列表记录,然后在列表中暴力枚举三个值。
# 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)
print(2430)
蓝桥1020
import os
import sys
# 请在此输入您的代码
# 每个数进行质因子分解
# 然后累计求出阶乘地质因子分解
from collections import Counter # 计数器,统计一个列表出现的次数
def f(n):
factor = []
for i in range(2, n + 1):
# 只要能够整除,我就不断地除,除到只剩质数,
while n % i == 0:
n //= i
factor.append(i)
if n == 1:
break
return factor
all_factor = []
for i in range(2, 101): # 阶乘是从1乘到100,所以求出每个数进行因数分解,之后乘也是一样的。
all_factor += f(i) # +是因为返回的是列表
all_factor = Counter(all_factor)
ans = 1
for k, v in all_factor.items(): # 取出因子和次数,其实只需要次数(指数or幂次)
ans *= v + 1
print(ans)
python中的Counter:
假设all_factor:
all_factor = [2, 3, 2, 5, 7, 2, 3, 2, 3]
输出结果将是:
Counter({2: 4, 3: 3, 5: 1, 7: 1})
意思是2有4个,3有3个...
蓝桥2131
对于中国剩余定理不熟悉,找规律:
x % 2 == 1, x % 3 == 2找到x == 5,但是还要满足后面的,比如 x % 4 == 1,但是又要维持前面的关系,所以可以每次加上前面的最小公倍数,保持余数不变,直到满足x % 4 == 1,然后再找2,3,4的最小公倍数,如此往复。
import math
ans = 5
lcm = 6
dic = [0,0,1,2,1,4,5,4,1,2,9,0,5,10,11,14,9,0,11,18,9,11,11,15,17,9,23,20,25,16,29,27,25,11,17,4,29,22,37,23,9,1,11,11,33,29,15,5,41,46]
for i in range(4, 50):
while ans % i != dic[i]:
ans += lcm
lcm = math.lcm(i, lcm)
print(i)
print(ans)
2.常识 + 进制
补充知识:
1 MB = 1024 KB
1 KB = 1024 bytes
32位整数占空间4bytes
64位整数占空间8bytes
蓝桥1565
print(200 // 8)
蓝桥1445
import os
import sys
# 请在此输入您的代码
space = 256 * 1024 * 1024 # 256 MB 转换为字节数
integer_size = 4 # 每个整数占用 4 字节
num_integers = space // integer_size
print(num_integers)
蓝桥1566
print(255)
蓝桥2095
简单做法:
内置int
print(int('2022',9)) # ’2022‘为9进制数,以十进制输出
Kto10模板:
int_to_char ="0123456789ABCDEF"
char_to_int = {}
for idx, char in enumerate(int_to_char):
char_to_int[char] = idx
#k进制数字x转换成10进制:0-9、A-E
def K_To_Ten(k,x):
ans = 0
for char in x:
ans = ans * k + char_to_int[char]
return ans
print(K_To_Ten(9, '2022'))
蓝桥2060
找规律题,也可以想先切行再切列(注意切开行的纸不是原来的纸)
import os
import sys
# 请在此输入您的代码
# 1: 4
# 2: 5
# 3: 7
print(4 + (440 - 1))
3.时间类问题
蓝桥2140
高次幂可以用快速幂来进行求解,不过这里不需要,算有多少个周期(星期)
print(6 + 20 ** 22 % 7)
蓝桥2096
枚举顺子,各个数位上有限制,比如前第一个数位不能大于1,第3个数位不能大于1。
枚举所有顺子的可能(包括大小和位置)然后再进行分类讨论。
# 2022012_ 10
# 2022_012 1
# 2022123_ 2
# 2022_123 2 - 1
print(14)
蓝桥1562
普通做法:
def ispingfang(STR):
# min 2001 1 1 - 5
# max 2019 9 29 - 32
return True if sum(map(int, STR)) in [9, 16, 25] else False
def ispingnian(year):
return False if ((not year % 4) and (year % 100)) or (not year % 400) else True
result = 0
for year in range(2001, 2022): # 枚举年份
for month in range(1, 13): # 枚举月份
d = 31
if month in [4, 6, 9, 11]: # 小月没有31号
d = 30
elif month == 2: # 2月特判
if ispingnian(year):
d = 28
else:
d = 29
for day in range(1, d+1):
result += ispingfang(str(year) + str(month) + str(day))
print(result)
datetime库做法
import os
import sys
# 请在此输入您的代码
import datetime
a=datetime.datetime(2001,1,1) # 设定起始日期
b=datetime.datetime(2021,12,31) # 设定结束日期
c=datetime.timedelta(days=1) # 设置时间差(步长),一天天遍历。
count=0
d=0
while a!=b: # 当时间没到b时
date=datetime.datetime.strftime(a,'%Y%m%d') # 格式化
for i in range(8): # 遍历前八位,也就是年月日
d+=int(date[i])
e=d**0.5
if e%1==0: # 如果开方完后是整数,说明是完全平方数,符合条件。
count+=1
d=0 # 重置d
a+=c # 步长 + 1
print(count)
蓝桥2119
这种时间问题,有一个很大特性是日期是否合法,比如闰年,小月大月,以及月份不能大于12等等,看具体题目情况,如果情况少直接手数枚举。
import os
import sys
# 请在此输入您的代码
#合法的日期(月日)取值仅有以下16种:
#0111,0222,1011,1211,1222,1101,1121,1110,1112,1113,1114,1115,1116,1117,1118,1119
#创建一个列表分别储存每个日期(月日)对应的合法时间个数:
time=[4,4,4,4,4,4,4,4,4,3,3,3,2,2,2,2]
#年份无限制,每个数乘4即可
year=[4*i for i in time]
print(sum(year))
蓝桥597
datetime做法
import os
import sys
# 请在此输入您的代码
import datetime
sum_num = 0
start_time = datetime.datetime(2000,1,1)
end_time = datetime.datetime(2020,10,1)
c = datetime.timedelta(days=1)
while start_time <= end_time:
a = start_time.weekday() # 星期几
b = start_time.day # 在一个月份中是第几天
if a == 0 or b == 1:
sum_num += 2
else:
sum_num += 1
start_time += c
print(sum_num)
蓝桥1038
# import os
# import sys
# # 请在此输入您的代码
# import datetime
# start_time = datetime.datetime(1900,1,1)
# end_time = datetime.datetime(9999,12,31)
# delta = datetime.timedelta(days=1)
# count = 0
# while start_time < end_time:
# if '2' in str(start_time):
# count += 1
# start_time += delta
# print(count + 1)
print(1994240)
其他:
蓝桥1449
思路是求出每两点之间的斜率和截距,每条直线都不同,使用一个集合统计达到去重的效果,然后加上斜率不存在的20条直线。
list = []
docker = set()
for i in range(20):
for j in range(21):
list.append([i, j])
for i in list:
x0, y0 = i[0], i[1]
for j in list:
x1, y1 = j[0], j[1]
if x0 == x1:
continue
k = (y1 - y0) / (x1 - x0)
b = (y1 * x0 - y0 * x1) / (x0 - x1)
if (k, b) not in docker:
docker.add((k,b))
print(len(docker) + 20)
蓝桥2188
import os
import sys
# 请在此输入您的代码
for s in range(0, 6): # 枚举小时数
for f in range(0,60): # 枚举分钟数
for m in range(0,60): # 枚举秒数
A = abs(30 * (s + f / 60 + m / 3600) - 6 * (f + m / 60)) # 计算时针与分针之间的角度
B = abs(6 * (f + m / 60) - 6 * m) # 计算分针与秒针之间的角度
A = A if A <= 180 else 360 - A
B = B if B <= 180 else 360 - B
if A == 2 * B and A > 0 and B > 0:
print(f'{s} {f} {m}')
蓝桥1444
for i in range(1,2022):
if (i*1000000007+999999999) % 2021 == 0:
print(int((i*1000000007+999999999) / 2021))
break
蓝桥2118
字符串不可变,所以转换为列表用sorted,也可用sort
然后用join连接列表为字符串
import os
import sys
# 请在此输入您的代码
a = 'WHERETHEREISAWILLTHEREISAWAY'
a = sorted(a)
list1 = (list(a))
print(''.join(list1))
蓝桥 1065
import os
import sys
# 请在此输入您的代码
f = """shenglue"""
s=f.split('\n')
row=len(s)
col=len(s[0])
ans = 0
for i in range(row):
for j in range(col):
if s[i][j]=='2': # 如果此位是2,搜索右边和下边,右下边有没有020
if j+3<col and s[i][j+1]+s[i][j+2]+s[i][j+3]=='020':
ans+=1
if i+3<row and s[i+1][j]+ s[i+2][j]+s[i+3][j]=='020':
ans+=1
if i+3<row and j+3<col and s[i+1][j+1]+s[i+2][j+2]+s[i+3][j+3]=='020':
ans += 1
#print(ans)
print(16520)
蓝桥2141
ans = 0
for i in range(2022, 2022222023):
a = str(i)
if a == a[::-1]: # 判断是否为回文数
is_non_decreasing = True
for j in range(len(a) // 2): # 检查从左到右数字递增或保持不变
if a[j] > a[j + 1]:
is_non_decreasing = False
break
if is_non_decreasing:
ans += 1
print(ans)
蓝桥1443
思路打开,什么时候结束?有一张用的最快,这张用完了就不能再拼了,所以只要暴力循环,等到用完了,记录答案退出就行。
import os
import sys
# 请在此输入您的代码
mid = 0
for i in range(1, 1000000):
mid += int(str(i).count('1'))
if mid > 2021:
ans = i - 1
break
print(ans)
蓝桥3500
出题人不可能让我们直接暴力,这个数太大了,只要求后面9位的数字,说明可能有规律可循。
后面发现从40!开始,后面9位的数字全是0,那么只需要从1一直加到40的阶乘,取后9位就可以了。
def get_jie(n):
if n <= 1:
return 1
ans = 1
for i in range(1, n + 1):
ans *= i
return ans
ans = 0
for i in range(1, 40):
ans += get_jie(i)
ans %= 10 ** 9
print(ans)
持续更新中...