python《王道机试》记录

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/

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值