题目请见https://python.xidian.edu.cn/problem.php?id=(题目编号,比如1000),如果这个网站关闭可以看评论区,本公众号会提供题目网站供大家查看,这里提供对应题目的代码,代码简洁,附带简单关键性解释(有些有必要一题多解的我也做了两个相对好一些的解答)
总共90道题,OJ上题目编号不连续,所以共90个题,这一章是前50题
先导篇
在做题之前,先了解输入输出:
(1)单行输入多个
a,b = map(int,input().split())
看到split就是把字符串分解成表格的常用办法
(2)多行输入
方法一:
a = []try: while True: a.append(input())except EOFError: # 接下来输入你的代码
方法二:
import systext = sys.stdin.read()
这个是将整个文本读入text,回车以'\n'存入textimport syslines = sys.stdin.read().splitlines()
string = ''try: for line initer(input, ''): string += line + '\n'except EOFError: string = string[0:-1] # 去除最后的回车
这个是西电oj上给的代码,解释一下,是iter(输入,哨兵值),回车相当于若输入空字符. 个人认为有点麻烦,但既然给了,就提一下,建议用上面两种,足够eval是执行语句,执行的范围很广,所以有时候为了安全起见,用下面的(但是做oj题这个够用了哈)import asta = ast.literal_eval(input())
支持的数据类型:字符串、数字、元组、列表、字典、布尔值、None
(4)输出:
number = 1234.5678print(f"{number}") # 1234.5678print(f"{number:.2f}") # 1234.57print(f"{number:.2e}") # 1.23e+03print(f"|{number:>10.2f}|") # | 1234.57|print(f"{number:,.2f}") # 1,234.57num = 123.46print(f'|{num:<10.2f}|') # |123.46 |print(f'|{num:^10.2f}|') # | 123.46 |print(f'|{num:0>10.2f}|') # |0000123.46|print(f'|{num:*^10.2f}|') # |**123.46**|
这个是规则
a, b = map(int, input().split())print(a + b)
map分配赋值,split按指定分隔符将字符串拆分成列表
1.Pyhton 的 Hello World
print("Python = Pile + sensensen")
2.python 成绩
a, b, c = map(int, input().split())d = int(a*0.2 + b*0.3 + c*0.5)print(d)
3.eval函数的使用1
4.math库的使用1
import mathprint(math.gamma(int(input())))
gamma是math模块的一个函数,是阶乘函数在实数和复数域范围的扩展.
5.字符串存在判定
a = input("")b = input("")if a in b: print("True")else: print("False")
in是一种常用的判断是否包含某一元素的方法
6.回文串的判断
a = input("")b = a[::-1]if a == b: print("True")else: print("False")
双冒号和-1让字符串倒过来
7.成绩分析
score = int(input())if score < 0 or score > 100: print("Error!")elif score >= 90: print("A")elif score >= 80: print("B")elif score >= 70: print("C")elif score >= 60: print("D")else: print("F")
利用elif将范围逐渐扩大
8.最大公约数
import matha = int(input())b = int(input())print(math.gcd(a, b))
gcd函数为最大公约数(当然可以自己用辗转相除法),该函数不能判断0,但oj没有设置输入0
9.输出偶数
n = int(input())for i in range(1, n+1): if i%2 == 0: print(i)
10.计算均值
n = int(input())b = 0for i in range(n): b += int(input())print(f'{b}{b/n:.5f}')
f''为format,有f后里面可以为{变量}的形式,:.nf为保留n位小数
11.计算阶乘
n = int(input())a,s = 1,0for i in range(1,n+1): a *= i s += aprint(s)
可以使用math库里面的factorial,但是上述算法更快,无需重复计算
12.汇率兑换
s = input()if s[-1] in ['R', 'r']: usd = eval(s[:-1])//6 print(f"{usd}D")elif s[-1] in ['D', 'd']: rmb = eval(s[:-1])*6 print(f"{rmb}R")else: print("Error!")
注意整除是双斜杠 // print里面那个单位尽量按照题目,用大写
13.进度条的显示
a = int(input())print("------start------")for i in range(a+1): p = (i/a)*100 c,d = '**'*i, '..'*(a-i) print(f"{p:>3.0f} %[{c}->{d}]")print("------end-----")
精度:这里是指进度条进度i的范围 >3.0f表示数字占三位而且右对齐保留整数 这个题理论应当用'start'.center(scale//2,'-') 但是oj系统有bug, end不在中间,而且随着精度变化start和end这两个字符串是不会变化的,所以不如直接打
14.因字数
a = int(input())i,j = 0,0while a % 4 == 0: a //= 4 i += 1while a % 7 == 0: a //= 7 j += 1print(i, j)
15.文章检测
stopword,string = '',''spaces,letters,numbers,characters,others = 0,0,0,0,0try: for line in iter(input, stopword): str += line + '\n'except EOFError: passstring = string[0:-1]for char in string: if char == ' ': spaces += 1 elif char.isdigit(): numbers += 1 elif char.isalpha(): letters += 1 else: others += 1print(f"{spaces} spaces, {numbers} numbers, " f"{letters} letters, {others} other characters.")
代码不难,只是很长,判断较为麻烦; 注意输出的逗号后面有空格,感兴趣的话可以使用正则表达式,利用findall查找
import re, systext = sys.stdin.read()spaces = len(re.findall(' ', text))numbers = len(re.findall('[0-9]', text))letters = len(re.findall('[A-Za-z]', text))others = len(text) - spaces - numbers - lettersprint(f"{spaces} spaces, {numbers} numbers, " f"{letters} letters, {others} other characters.")
16.eval函数的使用2
import mathx, y = 12,14print(eval(input()))
不只是加减乘除,还有其他数学运算,必须用math库
17.质数的和与积
x = int(input())def f(a): j = 2 while j * j <= a: if a % j == 0: return 0 else: j += 1 return 1a = 1for i in range(2, x//2+1): if f(i) and f(x-i): if i*(x-i) > a: a = i*(x-i)print(a)
定义判断质数的函数需要熟练掌握,非常常用 if判断非零就是成立,无需写==1
18.寻找多数元素
a = []try: while True: a.append(int(input()))except EOFError: b = [] for i in a: b.append(a.count(i)) print(max(b))
这个是最优方案,下面提供一种排序比较思维,可以了解
a = []try: while True: a.append(int(input()))except EOFError: passa.sort()h = 1c = []for i in range(len(a)-1): if a[i] == a[i+1]: h += 1 else: c.append(h) h = 1c.append(h)m = max(c)print(m)
将数字排序,之后只需要比相邻数字是否相同
19.判断素数
x = input()def f(a): j = 2 while j * j <= a: if a % j == 0: return False else: j += 1 return Trueif not x.isdigit(): print('invalid')else: print(f(int(x)))
20.所有参数的乘积
def multi(*a): b = 1 for i in range(len(a)): if not isinstance(a[i], (int, float)): return f'Invalid arg {i+1}' else: b *= a[i] return bprint(eval(input()))
定义函数时,参数必须是*a,因为要接受任意数量的元素,并把它们打包成元组,(*a)的名字是可变参数,可变参数在函数中被组装成一个元组.大家注意在测试的时候要输入multi(1,'a')才可以,不能直接输入字母,直接输字母eval不出来的,默认它是个变量,会提示没有定义
21.到底怎么样才能写好 Python?
22.CSV文件解析
import syslines = sys.stdin.read().splitlines()for line in lines: print(line.replace(',', '\t') + '\t')
一般读取偏文本的格式, 并只需文本处理 用sys库更为方便
# 另一种打法 不需要sys模块a = []try: while True: a.append(input())except EOFError: for x in a: x = x.replace(',', '\t') print(x+'\t')
23.重复元素的判定
n = int(input())b = 1a = [int(input()) for _ in range(n)]for i in range(1,n): if a[i] in a[0:i]: print('True') print(i+1) b = 0 breakif b: print('False')
a是一个列表,这种方式更加简洁,下划线(for _ )和i是一样的
24.计算集合的并
a = set(map(int,input().split()))b = set(map(int,input().split()))print(a | b)
25.计算标准差
# method 1a = []d = 0while True: try: a.append(int(input())) except EOFError: breakc = sum(a)/len(a)for i in a: d += (i-c)**2dev = (d/(len(a)-1))**0.5print("dev = {:.2}.".format(dev))
# method 2from statistics import stdevimport sysa = []for i in sys.stdin: a.append(int(i))dev = stdev(a)print("dev = {:.2}.".format(dev))
求样本标准差注意分母的总数要-1,也可以用statistics模块的stdev函数
26.键值查询
data = eval(input())key = input()print(data[key])
27.月份输出
m = int(input())months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]print(months[m-1])
28.字符串进制转换
n = int(input())print(hex(n))
29.CSV 文件转换成 JSON 文件
a = []try: while True: a.append(input().split(','))except EOFError: for i in range(1, len(a)): a[i] = dict(zip(a[0], a[i])) c = json.dumps(a[1:],sort_keys=True, indent=4) print(c)
组装成字典: dict(zip(key的列表, value的列表)) json.dumps将对象转化为json字符串,想要达到题目效果必须对key排序,同时缩进为4个字节
30.集合的交
a = set(map(int, input().split()))b = set(map(int, input().split()))print(a & b)
31.小型登陆系统
h = 0while True: a,b = input(),input() c = 0 if a == 'Pile': c += 1 if b == 'MAKIKAWAYI': c += 1 if c == 2: print('SUCCESS') break h += 1 if h == 3: print('FAILED') break
连续的if保证每个条件都过一遍
32.密码
# method 1n = int(input())a = [input() for _ in range(n)]for i in range(n): b = 0 if any(c.isupper() for c in a[i]): b += 1 if any(c.islower() for c in a[i]): b += 1 if any(c.isdigit() for c in a[i]): b += 1 if any(c in ['~','!','@','#','$','%','^'] for c in a[i]): b += 1 if b >= 3 and 8 <= len(a[i]) <= 16: print("YES") else: print("NO")
# method 2import reb = 0n = int(input())a = [input() for _ in range(n)]for i in a: b = 0 if re.search('[A-Z]', i): b += 1 if re.search('[a-z]', i): b += 1 if re.search('[0-9]', i): b += 1 if re.search('[~!@#$%^]', i): b += 1 if b >= 3 and 8 <= len(i) <= 16: print("YES") else: print("NO")
any括号里面需要内嵌for循环来表示对每一个元素进行遍历,节省空间; 第二种方法正则表达式直接找,可能更方便,但是是超纲内容
33.斐波那契数列Fibonacci问题
n = int(input())a = [int(input()) for _ in range(n)]m = max(a)b = [1]*(m+1)if m>=2: b[2]=2 for i in range(3,m+1): b[i]=b[i-1]+b[i-2]for i in range(n): print(b[a[i]])
这个题关键在于省时间,用递归函数会重复运算,于是可以采取比较厉害的一种思路: 取最大的一个数,把每一步都记录下来,然后要求哪一步,直接输出对应步数的值就行
34.列表实现筛选法求素数
def f(x): j = 2 while j * j <= x: if x % j == 0: return False else: j += 1 return Truea = int(input())b = 0c = []while b < 2: if f(a): b += 1 c.append(a) a -= 1print(sorted(c))
35.圆周率的计算
from random import random,seedDARTS = int(input())SEED = int(input())hits = 0.0seed(SEED)for i in range(1, DARTS+1): x, y = random(), random() dist = pow(x ** 2 + y ** 2, 0.5) if dist <= 1.0: hits = hits + 1pi = 4 * (hits/DARTS)print(f'{pi:.6f}')
seed的作用: 在SEED的值不变的情况下的每次生成的随机数列完全相同
import采取from的形式,节省空间,此时不用再写'random.',直接写模块里面的函数名称就行
36.凯撒密码
a = input()n = int(input())for i in a: if i.islower(): print(chr(ord('a') + (ord(i) - ord('a') + n) % 26), end='') elif i.isupper(): print(chr(ord('A') + (ord(i) - ord('A') + n) % 26), end='') else: print(i, end='')
ord将字符转换为ASCII码, chr将ASCII码转换为字符,这里注意用end=''避免回车
37.字符串重复判断
import asta = ast.literal_eval(input())b = []char = set(a[0])for i in range(1,len(a)): char &= set(a[i])for letter in char: m = min(word.count(letter) for word in a) b.append(m*letter)b = sorted(b)print('"'+''.join(b)+'"')
先用集合将相同的字符找出来,采用&=的形式比较巧, 在统计该字符出现的最少次数,都放到列表里,再排序即可
想打单引号,外侧就需要双引号,反之亦然 count表示统计个数 join是将点号前面的那个元素加到列表元素之间输出
这个题技术用得比较多,大家慢慢消化
38.卡片选择
n = int(input())a = list(map(int, input().split()))b = a.count(5)c = a.count(0)if c==0: print(-1)elif b//9<1: print(0)else: print((b//9*9)*'5'+c*'0')
需要注意0也可以被9整除, 这是oj自己设计的原则,只要余数是0就可以
要注意必须写b//9*9才可以,不能写b,整除过后再×9跟原来的数字不一样
39.Life, the Universe, and Everything
# method 1a = []while True: b = int(input()) if b == 42: break a.append(b)for i in a: print(i)
上面的打法是只要输入到42就停止输入并输出42之前的数字,在oj系统是可以过的,比较简洁
但是下面这种打法更好,是正规的打法
a = []try: while True: a.append(int(input()))except EOFError: for i in range(len(a)): if a[i] == 42: for j in a[:i]: print(j) break
40.23333
a, b = map(int, input().split())c = []if a == 0: print(0)while a != 0: d = a % b if d < 10: c.insert(0, d) else: c.insert(0, chr(ord('A') + d - 10)) a = a // bfor x in c: print(x, end='')
上面这个代码对任何正整数(10进制)都成立,掌握更全面的更好,至于题目的23333...不用管它,太狭隘
41.整数数列求和
n,a = map(int,input().split())b = []c = [a]*nfor i in range(n): b.append(a*pow(10,i))for i in range(1,n): c[i] = b[i] + c[i-1]print(sum(c))
为了省时间,这个题我也用了稍微进阶一些的算法: 利用差分数组求和
c = [a]*n意思是c是一个列表,里面有n个a, 只是一个初始化,我只想让c[0]=a就行,但是要有n个元素,否则表格超范围,你写c=[a]+[0]*(n-1)也没问题.先形成b列表[2,20,200,...]通过加法实现c数组[2,22,222,..](具体你读代码就能理解),最后c数组求和即可. 序列和,差分是一种要掌握的算法
42.星号三角形
a = eval(input())//2 + 1for i in range(1, a+1): print(' '*(a-i), end='') print('*'*(2*i-1), end='') print(' '*(a-i))
主要在于找规律
43.手机短号
n = int(input())a = [input() for _ in range(n)]for i in range(n): if len(a[i]) == 11: print('6' + a[i][-5:]) else: print("Halation - I can't join it!")
44.aaaa+bbbb
n = int(input())lst = []def asc2(x): c = 0 for i in range(4): c += ord(x[i]) << (24-8*i) return cfor j in range(n): a,b = input().split() lst.append(asc2(a)+asc2(b))for j in range(n): print(lst[j])
ord表示这个字符的ASCII码 <<表示左移,这个时候是二进制,依据题目应该8位8位地去移动
45.6翻了
import rea = input()b = re.sub('6{10,}', '27', a)print(re.sub('6{4,9}', '9', b))
经典正则表达式问题,需要用到sub函数,特点是可以找字符,个数限定可以是范围 {10,}表示大于等于10
{4,9}表示6的个数是4~9个,注意左右都是闭区间
46.有理数四则运算1
from fractions import Fractiona = Fraction(input())b = Fraction(input())c = a + bprint(f'{c.numerator}/{c.denominator}')
输出用分子比分母的形式可以有效地将0输出为0/1, 事实上还不如输出0,但只有我这样输出才能过oj系统 ...当然你可以分类讨论
47.时间复杂度1
def f(x): if x == 1: return 0 global cnt s = x for i in range(2, s): cnt += 1 if x % i == 0: return 1 return 2if __name__ == '__main__': a = [] try: while True: a.append(int(input())) except EOFError: b = [0,0] n = max(a) cnt = 0 for i in range(2, n + 1): f(i) b.append(cnt) for i in a: print(b[i])
这个题要求要高一些了,不仅到读懂代码,还要节约时间,这个节约的办法跟斐波那契数列那个题一个思路,就是取最大值,然后从表格里取出数字,因为每一个输入的数字对应cnt的值都要从2算到n
oj这个代码不是很简洁,不过还是按题目的整,只需要添加几行代码就行
48.时间复杂度2
import mathdef f(x): if x == 1: return 0 global cnt s = int(math.sqrt(x)) for i in range(2, s + 1): cnt += 1 if x % i == 0: return 1 return 2if __name__ == '__main__': cnt = 0 a = [] try: while True: a.append(int(input())) except EOFError: b = [0,0] n = max(a) for i in range(2, n + 1): f(i) b.append(cnt) for i in a: print(b[i])
49.admin 的密码问题
n = int(input())a,b,c = ['']*n,['']*n,[]alter = {'1':'@','0':'%','l':'L','O':'o'}for i in range(n): a[i],b[i] = input().split() for j in alter: if j in b[i]: b[i] = b[i].replace(j,alter[j]) if i not in c: c.append(i)if not c: if n == 1: print('There is 1 account and no account is modified') else: print(f'There are {n} accounts and no account is modified')else: print(len(c)) for i in c: print(a[i],b[i])
巧用字典替换 将多个字符串存入列表,ying这题还考你单复数...
50.分级
x = int(input())a = list(map(int, input().split()))m,n = map(int, input().split())for i in range(x): if m<=sum(a[:i])<=n and m<=sum(a[i:])<=n: print(i+1) break elif i==x-1: print(0)
这个题用卡范围的方法 虽然sum函数加了很多次但不会超时,而且时间比较短 在数字比较多的情况下,可以用下面的代码,更省时间
x = int(input())a = list(map(int, input().split()))m,n = map(int, input().split())y = 0z = sum(a)for i in range(x): y += a[i] if m<=y<=n and m<=z-y<=n: print(i+2) break elif i==n-1: print(0)
前50题就这样,欢迎提供更厉害的办法,感谢支持!
后40题更精彩,难度和广度总体会更高一些.