这里写目录标题
2021/2/28
'''
题目描述
给出年分m和一年中的第n天,算出第n天是几月几号。
输入描述:
输入包括两个整数y(1<=y<=3000),n(1<=n<=366)。
输出描述:
可能有多组测试数据,对于每组数据,
按 yyyy-mm-dd的格式将输入中对应的日期打印出来。
'''
run = [31,29,31,30,31,30,31,31,30,31,30,31]
pin = [31,28,31,30,31,30,31,31,30,31,30,31]
def if_run(year):
if (year%100!=0 and year %4 == 0) or (year%400 ==0):
return 1
else:
return 0
def panduan(num,list):
for month in range(1,13):
if num <= list[month-1]:
return month,num
else:
num = num - list[month-1]
while 1:
try:
tem = input().split(' ')
year,num = eval(tem[0]),eval(tem[1])
except:
break
run_if = if_run(year)
if run_if:
month,day = panduan(num,run)
else:
month,day = panduan(num,pin)
print("{:04d}-{:02d}-{:02d}".format(year,month,day))
知识点记录:
1.闰年的表示方式:(year%100!=0 and year %4 == 0) or (year%400 ==0)
,能被4整除或者100整除,或者能被400整除。
不知道为什么使用 & 和 |
时经常出错
2.format格式注意一下
3.year, days = list(map(int, input().split()))
看到类似这样的输入记录
map函数
map是python内置函数,会根据提供的函数对指定的序列做映射。
map(function,iterable,...)
1.可以输入一个函数
2.与zip()功能相似
map(None,[2,4,6],[3,2,1])
# 结果如下
[(2,3),(4,2),(6,1)]
3.实现类型转换,返回为一个列表
2021/3/1
'''
题目描述
设计一个程序能计算一个日期加上若干天后是什么日期。
输入描述:
输入第一行表示样例个数m,接下来m行每行四个整数分别表示年月日和累加的天数。
输出描述:
输出m行,每行按yyyy-mm-dd的个数输出。
示例1
输入
1
2008 2 3 100
输出
2008-05-13
'''
day = {1:[0,31,29,31,30,31,30,31,31,30,31,30,31],
0:[0,31,28,31,30,31,30,31,31,30,31,30,31]}
def isleapyear(year):
if (year%100!=0 and year %4 == 0) or (year%400 ==0):
return 1
else:
return 0
def numberofyear(year):
if isleapyear(year):
return 366
else:
return 365
num = int(input())
for i in range(num):
year,month,date,total = map(int,input().split())
#计算该年的一共的天数
run = isleapyear(year)
for i in range(month):
total += day[run][i]
total += date
#先确定年份,再确定日月
while 1:
#确定年份
numberyear=numberofyear(year)
if total > numberyear:
total = total - numberyear
year = year+1
else:
break
#确定月
run = isleapyear(year)
for month in range(1,13):
if total > day[run][month]:
total = total - day[run][month]
else:
break
print("{:04d}-{:02d}-{:02d}".format(year,month,total))
注意点:
1.根据月份计算日期时,注意时比较是一个月过完,例如2月3日为1月的日期+3
第一次计算时错误多计算一个月
2.按照模块来,依次判断年——月——日,可以将计算的该年的日期计算成天数加到累计天数中,再和年份的天数进行判断
'''
题目描述
有一个长度为整数L(1<=L<=10000)的马路,可以想象成数轴上长度为L的一个线段,起点是坐标原点,在每个整数坐标点有一棵树,即在0,1,2,...,L共L+1个位置上有L+1棵树。 现在要移走一些树,移走的树的区间用一对数字表示,如 100 200表示移走从100到200之间(包括端点)所有的树。 可能有M(1<=M<=100)个区间,区间之间可能有重叠。现在要求移走所有区间的树之后剩下的树的个数。
输入描述:
两个整数L(1<=L<=10000)和M(1<=M<=100)。
接下来有M组整数,每组有一对数字。
输出描述:
可能有多组输入数据,对于每组输入数据,输出一个数,表示移走所有区间的树之后剩下的树的个数。
示例1
输入
500 3
100 200
150 300
470 471
输出
298
'''
while 1:
try:
l,group_num = map(int,input().split())
group = []
for i in range(group_num):
left,right = map(int,input().split())
group.append((left,right))
#初始化线段
road = [1 for i in range(l+1)]
for i in group:
for index in range(i[0],i[1]+1):
road[index] = 0
num = sum(road)
print(num)
except:
break
1.对于不同组的数据,可以输一组计算一组,全部读入并保存起来其实没有必要
2.列表可以像这样相乘,对于清零的部分,其实也可以用列表的切片来做,比for循环要节约时间
In[2]: [1]*7
Out[2]: [1, 1, 1, 1, 1, 1, 1]
'''
题目描述
按照手机键盘输入字母的方式,计算所花费的时间 如:a,b,c都在“1”键上,输入a只需要按一次,输入c需要连续按三次。 如果连续两个字符不在同一个按键上,则可直接按,如:ad需要按两下,kz需要按6下 如果连续两字符在同一个按键上,则两个按键之间需要等一段时间,如ac,在按了a之后,需要等一会儿才能按c。 现在假设每按一次需要花费一个时间段,等待时间需要花费两个时间段。 现在给出一串字符,需要计算出它所需要花费的时间。
输入描述:
一个长度不大于100的字符串,其中只有手机按键上有的小写字母
输出描述:
输入可能包括多组数据,对于每组数据,输出按出Input所给字符串所需要的时间
示例1
输入
复制
bob
www
输出
复制
7
7
'''
keytab = [1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,4,1,2,3,1,2,3,4]
while True:
time = 0
try:
str = input()
for i in range(len(str)):
time += keytab[ord(str[i]) - ord('a')]
if i!= 0 and ord(str[i]) - ord(str[i-1]) == keytab[ord(str[i])-ord('a')] - keytab[ord(str[i-1]) - ord('a')]:
time += 2
print(time)
except:
break
这题不会做,看的别人的答案。
知识点:
ord()和chr()
1.ord()函数主要用来返回对应字符的ascii码,chr()主要用来表示ascii码对应的字符他的输入时数字,可以用十进制,也可以用十六进制。
ord('a')
Out[3]: 97
chr(97)
Out[5]: 'a'
可通过ord()计算字母之间的距离,从而得到0~25表示26个字母的下标
(感觉对于python来说,也可以用字典进行存取数据,直接做出来,但如果数据稍微多一点的话就不是很方便,对其它语言也不太好用)
'''
题目描述
对输入的n个数进行排序并输出。
输入描述:
输入的第一行包括一个整数n(1<=n<=100)。
接下来的一行包括n个整数。
输出描述:
可能有多组测试数据,对于每组数据,将排序后的n个整数输出,每个数后面都有一个空格。
每组测试数据的结果占一行。
'''
while 1:
try:
num = input()
number = map(int,input().split())
number = sorted(number)
for i in number:
print("{} ".format(i),end='')
print()
except:
break
'''
题目描述
用一维数组存储学号和成绩,然后,按成绩排序输出。
输入描述:
输入第一行包括一个整数N(1<=N<=100),代表学生的个数。
接下来的N行每行包括两个整数p和q,分别代表每个学生的学号和成绩。
输出描述:
按照学生的成绩从小到大进行排序,并将排序后的学生信息打印出来。
如果学生的成绩相同,则按照学号的大小进行从小到大排序。
'''
a = int(input())
m = []
b = []
for i in range(a):
b = list(map(int,input().split()))
m.append(b)
m.sort(key = lambda x:(x[1],x[0]))
for i in m:
print(' '.join(map(str,i)))
自己写的太麻烦了,贴别人的代码
知识点分析:
list.sort()
list.sort(cmp=None, key=None, reverse=False)
cmp – 可选参数, 如果指定了该参数会使用该参数的方法进行排序。
key – 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
reverse – 排序规则,reverse = True 降序, reverse = False 升序(默认)。
2021/3/29
'''
题目描述
You are given a sequence of integer numbers. Zero-complexity transposition of the sequence is the reverse of this sequence. Your task is to write a program that prints zero-complexity transposition of the given sequence.
输入描述:
For each case, the first line of the input file contains one integer n-length of the sequence (0 < n ≤ 10 000). The second line contains n integers numbers-a1, a2, …, an (-1 000 000 000 000 000 ≤ ai ≤ 1 000 000 000 000 000).
输出描述:
For each case, on the first line of the output file print the sequence in the reverse order.
'''
#栈
class Stack:
def __init__(self):
self.stack = []
def push(self,value):
self.stack.append(value)
def pop(self):
value = self.stack.pop()
return value
def empty(self):
if len(self.stack)==0:
return True
else:
return False
def size(self):
return len(self.stack)
def top(self):
if self.empty():
return "None"
else:
return self.stack[self.size()-1]
while 1:
try:
stack = Stack()
num = int(input())
list1 = map(int,input().split())
for i in list1:
stack.push(i)
while not stack.empty():
value = stack.pop()
print(value,end=' ')
print()
except:
break
用到了栈的概念,比较新奇,其实就是列表封装一下啦。
觉得这道题逆序也能做
while 1:
try:
num = int(input())
#需要强转成列表类型
list1 = list(map(int, input().split()))
size = len(list1)
for i in range(size-1,-1,-1):
print(list1[i],end=' ')
print()
except:
break
需要注意的是使用map函数后,list1不是列表类型,因此需要转成列表类型。
在这里,其实不需要转换成整数类型,因为只需要输出而已,且使用list1.reverse()
直接反转后输出即可。
2021/07/03
1.进制转换
"""
进制转换
1.求模得到最低位
2.整除
"""
'''
描述
大家都知道,数据在计算机里中存储是以二进制的形式存储的。 有一天,小明学了C语言之后,他想知道一个类型为unsigned int 类型的数字,存储在计算机中的二进制串是什么样子的。 你能帮帮小明吗?并且,小明不想要二进制串中前面的没有意义的0串,即要去掉前导0。
输入描述:
多行,每一行表示要求的数字
输出描述:
输出共T行。每行输出求得的二进制串。
'''
#############题解1#######################
while 1:
try:
ten = eval(input())
except:
break
two = []
while ten!=0:
b = ten%2
#print(b)
two.append(str(b))
#整除
ten = ten//2
#将列表变成字符串
two = ''.join(two)
#逆序
two = two[::-1]
print(two)
#############题解2#######################
while True:
try:
s=int(input())
print(bin(s)[2:])
except:
break
#############题解3#######################
while True:
try:
n=int(input())
print(format(n,'b'))
except:
break
#############题解4#######################
while(1):
try:
s=int(input())
re=[]
while(s!=0):
re.append(s%2)
s=int(s/2)
for i in range(len(re)):
###################注意pop()####################
print(re.pop(),end='')
print()
except:
break
'''
描述
对于一个十进制数A,将A转换为二进制数,然后按位逆序排列,再转换为十进制数B,我们称B为A的二进制逆序数。 例如对于十进制数173,它的二进制形式为10101101,逆序排列得到10110101,其十进制数为181,181即为173的二进制逆序数。
输入描述:
一个1000位(即10^999)以内的十进制数。
输出描述:
输入的十进制数的二进制逆序数。
'''
s = int(input())
a_r = str(format(s,'b'))[::-1]
#将2进制转换成10进制输出
print(int(a_r,2))
'''
描述
将M进制的数X转换为N进制的数输出。
输入描述:
输入的第一行包括两个整数:M和N(2<=M,N<=36)。
下面的一行输入一个数X,X是M进制的数,现在要求你将M进制的数X转换成N进制的数输出。
输出描述:
输出X的N进制表示的数。
'''
r1, r2 = map(int, input().split())
# 转成10进制
s_10 = int(input(), 10)
number = '0123456789abcdefghijklmnopqrstuvwxyz'
# 将10进制转换成任意进制
def convert(x, r):
# 将十进制数x转换成r进制
re = ''
while x != 0:
c = x % r
re = re+number[c]
x = x//r
re = re[::-1]
return re
print(convert(s_10, r2))
总结
任意进制之间的转换:先转成10进制,再转成相应进制
int(x,r)
其中x为r进制的数,注意x为一个字符串,将任意进制的数转为十进制- 使用代码中最后的convert()函数可以转换成任意进制
–转化成2进制,bin(s)[2:]
或者format(s,'b')
–直接转换的时候要注意逆序 - 注意数为0时的情况,一定要进行判断,否则没有输出
map(int,input().split())
时一定要注意,如果是十进制以上的数,应该读入为字符串,无法变成整型,程序会报错,此时可以将需要变的分别强制类型转换。应该只使用input().split()
'''
描述
输入两个不超过整型定义的非负10进制整数A和B(<=231-1),输出A+B的m (1 < m <10)进制数。
输入描述:
输入格式:测试输入包含若干测试用例。每个测试用例占一行,给出m和A,B的值。 当m为0时输入结束。
输出描述:
输出格式:每个测试用例的输出占一行,输出A+B的m进制数。
'''
while 1:
try:
m,A,B = map(int,input().split())
if m ==0:
break
else:
x = A+B
num = ''
if x == 0:
print(0)
else:
while x:
num = num+str(x%m)
x = x//m
print(num[::-1])
except:
break
2.最大公约数最小公倍数
'''
最大公约数和最小公倍数
最大公约数:辗转相除法
最小公倍数:两数相乘除以最大公约数
'''
#################递归
def GCD(a,b):
if b==0:
return a
else:
return GCD(b,a%b)
while 1:
try:
a,b = map(int,input().split())
print(GCD(a,b))
except:
break
#################非递归
while 1:
try:
a,b = map(int,input().split())
while b:
a,b = b,a%b
print(a)
except:
break
'''
描述
给出n个正整数,任取两个数分别作为分子和分母组成最简真分数,编程求共有几个这样的组合。
输入描述:
每组包含n(n<=600)和n个不同的整数,整数大于1且小于等于1000。
输出描述:
每行输出最简真分数组合的个数。
'''
def GCD(a, b):
if b == 0:
return a
else:
return GCD(b, a % b)
while 1:
try:
num = 0
n = int(input())
num_l = input().split()
for i in range(n):
for j in range(i + 1, n):
# print(int(num_l[i]), int(num_l[j]))
if GCD(int(num_l[i]), int(num_l[j])) == 1:
num = num + 1
print(num)
except:
break
总结
- 最大公约数,辗转相除法
- 最小公倍数等于两数相乘除以最大公约数
- 最简真分数——>两数互质——>最大公约数为1
2021/07/04
1.素数
'''
质数,素数——只能被自身和1整除的正整数,0,1和负数都是非素数
for i in range(2,int(math.sqrt(n))+1):
找出0~100000之间的所有素数——素数筛法,标记素数的倍数为非素数
'''
'''
描述
给定一个数n,要求判断其是否为素数(0,1,负数都是非素数)。
输入描述:
测试数据有多组,每组输入一个数n。
输出描述:
对于每组输入,若是素数则输出yes,否则输入no。
'''
import math
def sushu(n):
if n < 2:
return 'no'
elif n==2 or n ==3:
return 'yes'
else:
for i in range(2,int(math.sqrt(n))+1):
if n%i==0:
return 'no'
return 'yes'
while 1:
try:
n = int(input())
print(sushu(n))
except:
break
'''
描述
输入一个整数n(2<=n<=10000),要求输出所有从1到这个整数之间(不包括1和这个整数)个位为1的素数,如果没有则输出-1。
输入描述:
输入有多组数据。 每组一行,输入n。
输出描述:
输出所有从1到这个整数之间(不包括1和这个整数)个位为1的素数(素数之间用空格隔开,最后一个素数后面没有空格),如果没有则输出-1。
'''
# 计算2~10000之间的素数
sushu = [0 for i in range(10001)]
for i in range(2, 10001):
if sushu[i] == 0:
# 标记其所有倍数
for j in range(i * i, 10001, i):
sushu[j] = 1
while 1:
try:
n = int(input())
s = []
for i in range(2, n):
if sushu[i] == 0 and i % 10 == 1:
s.append(i)
if len(s) == 0:
print(-1)
else:
for i in range(len(s) - 1):
print(s[i], end=' ')
print(s[len(s) - 1])
except:
break
'''
描述
Output the k-th prime number.
输入描述:
k≤10000
输出描述:
The k-th prime number.
'''
sushu = [0 for i in range(1000000)]
re = [0]
flag = 0
for i in range(2,1000000):
if sushu[i]==0:
re.append(i)
flag = flag+1
if flag>10000:
break
for j in range(i*i,1000000,i):
sushu[j]=1
while 1:
try:
n = int(input())
print(re[n])
except:
break
总结
-
质数,素数——只能被自身和1整除的正整数,0,1和负数都是非素数
-
for i in range(2,int(math.sqrt(n))+1):
-
找出0~100000之间的所有素数——素数筛法,标记素数的倍数为非素数(后两道题)
2.分解质因数
```c
'''
分解质因数
素数通常用于分解质因数,每个数都可以写成几个或1个质数相乘的形式,其中每个质数都是这个数的质因数
'''
'''
描述
求正整数N(N>1)的质因数的个数。 相同的质因数需要重复计算。如120=2*2*2*3*5,共有5个质因数。
输入描述:
可能有多组测试数据,每组测试数据的输入是一个正整数N,(1<N<10^9)。
输出描述:
对于每组数据,输出N的质因数的个数。
'''
import math
max = int(math.sqrt(1e9)) + 1
re = [0 for i in range(max)]
sushu = []
for i in range(2, max):
if re[i] == 0:
sushu.append(i)
for j in range(i * i, max, i):
re[j] = 1
def power(x, n):
num = 0
while 1:
if x % n == 0:
x = x / n
num = num + 1
else:
return x, num
while 1:
try:
n = int(input())
num = len(sushu)
count = 0
max1 = int(math.sqrt(n)) + 1
for i in range(num):
if sushu[i] < max1:
n, num = power(n, sushu[i])
count = count + num
else:
break
if n != 1:
count = count + 1
print(count)
except:
break
'''
描述
输入n个整数,依次输出每个数的约数的个数
输入描述:
输入的第一行为N,即数组的个数(N<=1000) 接下来的1行包括N个整数,其中每个数的范围为(1<=Num<=1000000000)
输出描述:
可能有多组输入数据,对于每组输入数据, 输出N行,其中每一行对应上面的一个数的约数的个数。
'''
import math
def divisor(n):
# 计算约数的个数
s = math.sqrt(n)
max = int(s) + 1
count = 0
for i in range(1, max):
if n % i == 0:
count = count + 2
if int(s) == s:
count = count - 1
return count
while 1:
try:
n = int(input())
b = list(map(int, input().split()))
for i in b:
print(divisor(i))
except:
break
'''
描述
给定n,a求最大的k,使n!可以被a^k整除但不能被a^(k+1)整除。
输入描述:
两个整数n(2<=n<=1000),a(2<=a<=1000)
输出描述:
一个整数.
'''
def division(x, a):
count = 0
while 1:
if x % a == 0:
count = count + 1
x = x // a
else:
break
return count
x, a = map(int, input().split())
num = 1
for i in range(1, x + 1):
num = num * i
print(division(num, a))
##############################使用质因数分解的方法
import math
# 计算1000以内的素数
# 素数筛法
max = 1000 + 1
re = [0 for i in range(max)]
sushu = []
for i in range(2, max):
if re[i] == 0:
sushu.append(i)
for j in range(i * i, max, i):
re[j] = 1
# 计算a和n的质因子
def division(x, n):
num = 0
while 1:
if x % n == 0:
num = num + 1
x = x // n
else:
break
return x, num
def prime(n):
maxp = math.sqrt(n) + 1
factor = {}
for i in range(1000):
if sushu[i] > maxp:
break
else:
n, num = division(n, sushu[i])
factor[sushu[i]] = num
if n != 1:
factor[n] = 1
return factor
def primen(x):
factor = {}
for n in range(2,x+1):
maxp = math.sqrt(n) + 1
for i in range(1000):
if sushu[i] > maxp:
break
else:
n, num = division(n, sushu[i])
try:
factor[sushu[i]] = factor[sushu[i]]+num
except:
factor[sushu[i]] = num
if n != 1:
factor[n] = 1
return factor
n, a = map(int, input().split())
np = primen(n)
np_fa = np.keys()
ap = prime(a)
k = -1
flag = 1
while 1:
k = k + 1
for factor, num in ap.items():
if factor in np_fa:
np[factor] = np[factor] - num
if np[factor] < 0:
flag = 0
break
else:
flag = 0
break
if flag == 0:
break
print(k)
总结
- 累了以后再写
- 求约数和整除问题都与质因子有点关系
2021/07/05
1.快速幂
'''
快速幂与取模相关
'''
'''描述
N<k时,root(N,k) = N,否则,root(N,k) = root(N',k)。N'为N的k进制表示的各位数字之和。输入x,y,k,输出root(x^y,k)的值 (这里^为乘方,不是异或),2=<k<=16,0<x,y<2000000000,有一半的测试点里 x^y 会溢出int的范围(>=2000000000)
输入描述:
每组测试数据包括一行,x(0<x<2000000000), y(0<y<2000000000), k(2<=k<=16)
输出描述:
输入可能有多组数据,对于每一组数据,root(x^y, k)的值'''
while 1:
try:
x,y,k = map(int,input().split())
N = 1
while y>0:
if y%2==1:
N = (N*x)%(k-1)
#用移位更快
y = y>>1
x = (x*x)%(k-1)
if N == 0:
print(k-1)
else:
print(N)
except:
break
总结
- 取模的运算法则
(a + b) % p = (a % p + b % p) % p (1)
(a - b) % p = (a % p - b % p ) % p (2)
(a * b) % p = (a % p * b % p) % p (3)
因此如果取后三位的话可以每次都先取再乘积,减小运算量和内存 - 快速幂
快速幂算法讲解:https://blog.youkuaiyun.com/qq_19782019/article/details/85621386
解题思路:https://www.freesion.com/article/5577339721/