文章目录

  • 一、牛客-简单类
  • 1、HJ81 字符串字符匹配--SET使用
  • 2、二维数组操作--map(),split()使用
  • 3、HJ8 合并表记录--sorted()、字典输出
  • 4、HJ80 整型数组合并--join()、set()、多input写一行、列表转字符串
  • 5、HJ6 质数因子--while与if、math.sqrt、end=" "、整除//
  • 6、HJ51 输出单向链表中倒数第k个结点
  • 7、HJ36 字符串加密--ord()、chr()
  • 8、HJ105 记负均正II
  • 二、牛客-中等类
  • 1、HJ41 称砝码-zip()、列表*数字、集合遍历、集合增加元素
  • 2、HJ17 坐标移动--异常捕获、res[0,0]存储元素、长度判断
  • 3、HJ63 DNA序列--一段长度字符串输出指定长度时的遍历妙用、count
  • 4、HJ92 在字符串中找出连续最长的数字串--isalpha()、replace、
  • 5、HJ32 密码截取--回文子串
  • 6、HJ33 整数与IP地址间的转换-bin()、int(X,2)、'0'*(8-len(s))
  • 7、HJ20 密码验证合格程序--return 0、ord判断类型大于2、相同子串判断
  • 8、HJ69 矩阵乘法--二维矩阵,不换行输出
  • 9、HJ67 24点游戏算法--permutations
  • 10、HJ103 Redraiment的走法--动态规划、reversed
  • 11、HJ82 将真分数分解为埃及分数----while a、range步长
  • 12、HJ74 参数解析----字符串转换
  • 13、HJ24 合唱队
  • 14、HJ52 计算字符串的编辑距离--动态规划
  • 三、牛客-较难类
  • 1、HJ3 明明的随机数--set
  • 2、HJ42 学英语
  • 3、HJ68 成绩排序
  • 4、HJ89 24点运算--dict(zip())、字母转数字并运用、return
  • 5、HJ95 人民币转换
  • 6、HJ93 数组分组--递归方式学习、sum
  • 7、HJ39 判断两个IP是否属于同一子网



一、牛客-简单类

1、HJ81 字符串字符匹配–SET使用

描述
判断短字符串S中的所有字符是否在长字符串T中全部出现。
请注意本题有多组样例输入。
数据范围:1\le len(S),len(T)\le200\1≤len(S),len(T)≤200
进阶:时间复杂度:O(n)\O(n) ,空间复杂度:O(n)\O(n)
输入描述:
输入两个字符串。第一个为短字符串,第二个为长字符串。两个字符串均由小写字母组成。
输出描述:
如果短字符串的所有字符均在长字符串中出现过,则输出字符串"true"。否则输出字符串"false"。
示例1
输入:
bc
abc
复制
输出:
true
复制
说明:
其中abc含有bc,输出"true"

while True:
    try:
        s1=input()
        s2=input()
        if set(s1)<=set(s2):
            print("true")
        else:
            print("false")
    except:
        break

set():创建一个无序不重复元素集,能够进行交集、并集、差集计算。

2、二维数组操作–map(),split()使用

map():根据提供的函数,对指定序列进行转换,返回迭代器。一般转换为list。
split():通过分隔符对字符串进行分隔,第二个参数num默认为-1,代表分隔所有,否则则分隔为num+1个元素。返回值为列表。

描述
有一个mn\m∗n 大小的数据表,你会依次进行以下5种操作:
1.输入m\m 和n\n ,初始化m
n\m∗n 大小的表格。
2.输入x_1x1、y_1y1、x_2x2、y_2y2,交换坐标在(x_1,y_1)(x1,y1)和(x_2,y_2)(x2,y2)的两个数。
3.输入x\x ,在第x\x 行上方添加一行。
4.输入y\y ,在第y\y 列左边添加一列。
5.输入x\x 、y\y ,查找坐标为(x,y)(x,y) 的单元格的值。
请编写程序,判断对表格的各种操作是否合法。
详细要求:
1.数据表的最大规格为9行9列,对表格进行操作时遇到超出规格应该返回错误。
2.对于插入操作,如果插入后行数或列数超过9了则应返回错误。如果插入成功了则将数据表恢复至初始化的m
n\m∗n 大小,多出的数据则应舍弃。
3.所有输入坐标操作,对m*n\m∗n 大小的表格,行号坐标只允许0m-1,列号坐标只允许0n-1。超出范围应该返回错误。
本题含有多组样例输入!行列从0开始标号
数据范围:数据组数:1\le t\le 5\1≤t≤5
进阶:时间复杂度:O(1)\O(1) ,空间复杂度:O(1)\O(1)
输入描述:
输入数据按下列顺序输入:
1 表格的行列值
2 要交换的两个单元格的行列值
3 输入要插入的行的数值
4 输入要插入的列的数值
5 输入要查询的单元格的坐标
输出描述:
输出按下列顺序输出:
1 初始化表格是否成功,若成功则返回0, 否则返回-1
2 输出交换单元格是否成功
3 输出插入行是否成功
4 输出插入列是否成功
5 输出查询单元格数据是否成功
示例1
输入:
4 9
5 1 2 6
0
8
2 3
4 7
4 2 3 2
3
3
4 7
复制
输出:
0
-1
0
-1
0
0
-1
0
0
-1
复制
说明:
本组样例共有2组样例输入。
第一组样例:
1.初始化数据表为4行9列,成功
2.交换第5行1列和第2行6列的数据,失败。因为行的范围应该是(0,3),不存在第5行。
3.在第0行上方添加一行,成功。
4.在第8列左边添加一列,失败。因为列的总数已经达到了9的上限。
5.查询第2行第3列的值,成功。
第二组样例:
1.初始化数据表为4行7列,成功
2.交换第4行2列和第3行2列的数据,失败。因为行的范围应该是(0,3),不存在第4行。
3.在第3行上方添加一行,成功。
4.在第3列左边添加一列,成功。
5.查询第4行7列的值,失败。因为虽然添加了一行一列,但数据表会在添加后恢复成4行7列的形态,所以行的区间仍然在[0,3],列的区间仍然在[0,6],无法查询到(4,7)坐标。

while True:
    try:
        m,n=map(int,input().split())
        x,y,z,t=map(int,input().split())
        insert_x=int(input())
        insert_y=int(input())
        i,j=map(int,input().split())
        if 0<m<=9 and 0<n<=9:
            print(0)
        else:
            print(-1)
        if 0<=x<m and 0<=y<n and 0<=z<m and 0<=t<n:
            print(0)
        else:
            print(-1)
        if 0<=insert_x<m and m<9:
            print(0)
        else:
            print(-1)
        if 0<=insert_y<n and n<9:
            print(0)
        else:
            print(-1)
        if 0<=i<m and 0<=j<n:
            print(0)
        else:
            print(-1)
    except:
        break

3、HJ8 合并表记录–sorted()、字典输出

sorted():针对可遍历对象进行排序,生成新的列表。
sort():只可针对列表排序。

# 针对字典,则根据key进行默认的升序,然后输出key的升序列表
a={'0':'5','1':'7'}
sorted(a)

>>>[0,1]
# 第二个参数:key
a=[{'age':25,'name':'Jack'},{'age':20,'name':'Mack'}]
sorted(a,key=lambda x:x['age'])
>>>[{'age':20,'name':'Mack'},{'age':25,'name':'Jack'}]
# 第三个参数:reserve=False,默认Falue为升序,True为倒序。
a=[3,2,6,7,1]
sorted(a,reserve=True)
>>>[7,6,3,2,1]

描述
数据表记录包含表索引index和数值value(int范围的正整数),请对表索引相同的记录进行合并,即将相同索引的数值进行求和运算,输出按照index值升序进行输出。
提示:
0 <= index <= 11111111
1 <= value <= 100000
输入描述:
先输入键值对的个数n(1 <= n <= 500)
接下来n行每行输入成对的index和value值,以空格隔开
输出描述:
输出合并后的键值对(多行)
输入:
4
0 1
0 2
1 2
3 4
复制
输出:
0 3
1 2
3 4

while True:
    try:
        n=int(input())
        dct={}
        for i in range(n):
            key,value=map(int,input().split())
            if key not in dct:
                dct[key]=value
            else:
                dct[key]+=value
        for i in sorted(dct):
            print(i,dct[i])
    except:
        break

4、HJ80 整型数组合并–join()、set()、多input写一行、列表转字符串

join():将序列(可以是字符串,不能是int)以指定的字符进行拼接,形成字符串。
列表变成字符串map(str,lst)

描述
题目标题:
将两个整型数组按照升序合并,并且过滤掉重复数组元素。
输出时相邻两数之间没有空格。
输入描述:
输入说明,按下列顺序输入:
1 输入第一个数组的个数
2 输入第一个数组的数值
3 输入第二个数组的个数
4 输入第二个数组的数值
输出描述:
输出合并之后的数组
示例1
输入:
3
1 2 5
4
-1 0 3 2
复制
输出:
-101235

while True:
    try:
        m,x,n,y=input(),input().split(),input(),input().split()
        res=map(str,sorted(map(int,set(x+y))))
        print(''.join(res))
    except:
        break

5、HJ6 质数因子–while与if、math.sqrt、end=" "、整除//

描述
功能:输入一个正整数,按照从小到大的顺序输出它的所有质因子(重复的也要列举)(如180的质因子为2 2 3 3 5 )
数据范围: 1 \le n \le 2 \times 10^{9} + 14 \1≤n≤2×10
9
+14
输入描述:
输入一个整数
输出描述:
按照从小到大的顺序输出它的所有质数的因子,以空格隔开。
示例1
输入:
180
复制
输出:
2 2 3 3 5

import math
while True:
    try:
        n=int(input())
        for i in range(2,int(math.sqrt(n))+1):
                while n%i==0:
                    print(i,end=" ")
                    n=n//i
        if n>2:
            print(n)
    except:
        break
# 可能质数因子是本身
# 可能剩下来的质数大于n^1/2
# math.sqrt()的使用,这是求质数时减少算法的必用方法
# 最好的办法:每次能被除的时候,直接输出,结尾带上end=" "
# n=n//i,每次被除完,n需要更新值。且//代表整除,/有1位小数。
# while 和 if的区别:if循环语句只执行1次,成功就不回来。while条件判断,遇到FALSE才退出循环

6、HJ51 输出单向链表中倒数第k个结点

解题思路:创建节点类,创建链表类(包含判断是否为空、元素添加、输出第N个节点值)。目标函数:创建实例,再调用添加、输出的方法。

描述
输入一个单向链表,输出该链表中倒数第k个结点,链表的倒数第1个结点为链表的尾指针。
链表结点定义如下:
struct ListNode
{
int m_nKey;
ListNode* m_pNext;
};
正常返回倒数第k个结点指针,异常返回空指针.
要求:
(1)正序构建链表;
(2)构建后要忘记链表长度。
数据范围:链表长度满足 1 \le n \le 1000 \1≤n≤1000 , k \le n \k≤n ,链表中数据满足 0 \le val \le 10000 \0≤val≤10000
本题有多组样例输入。
输入描述:
输入说明
1 输入链表结点个数
2 输入链表的值
3 输入k的值
输出描述:
输出一个整数
示例1
输入:
8
1 2 3 4 5 6 7 8
4
复制
输出:
5

# 定义一个结点类
class Node(object):
    # 初始化类的属性
    def __init__(self,data):
        self.data=data
        self.next=None # 用来保存下一个结点对象,初始化为None
# 定义一个链表类
class LinkList(object):
    def __init__(self,node=None):
        self.head=node
        
    # 判断链表是否为空
    def is_empty(self):
        if self.head is None:
            return True
        else:
            return False
    
    # 链表尾部添加对象,首先一定得判断链表是否为空
    def append(self,item):
        node=Node(item) # 用item的值,创建链表
        
        if self.is_empty():
            self.head=node
        
        else:
            cur=self.head 
            
            while cur.next is not None:
                cur=cur.next 
            cur.next=node
            
    # 输出打印第N个节点的值
    def print_node(self,num):
        cur=self.head
        for i in range(0,num-1):
            cur=cur.next 
        print(cur.data)

if __name__=='__main__':
    while True:
        try:
            n,lst,k=int(input()),input().split(),int(input())
            if k==0:
                print(0)
            else:
                # 注意给单链表添加元素的方法
                link_lst=LinkList()
                for i in lst:
                    link_lst.append(i)
            link_lst.print_node(n-k+1)  # 此处可直接输出结果
        except:
            break

7、HJ36 字符串加密–ord()、chr()

chr()–将数字转为ASCII字符
ord()–将ASCII字符转为数值
解题关键:先遍历原字符串,去除重复字母;再遍历26个字母。

描述
有一种技巧可以对数据进行加密,它使用一个单词作为它的密匙。下面是它的工作原理:首先,选择一个单词作为密匙,如TRAILBLAZERS。如果单词中包含有重复的字母,只保留第1个,将所得结果作为新字母表开头,并将新建立的字母表中未出现的字母按照正常字母表顺序加入新字母表。如下所示:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
T R A I L B Z E S C D F G H J K M N O P Q U V W X Y (实际需建立小写字母的字母表,此字母表仅为方便演示)
上面其他用字母表中剩余的字母填充完整。在对信息进行加密时,信息中的每个字母被固定于顶上那行,并用下面那行的对应字母一一取代原文的字母(字母字符的大小写状态应该保留)。因此,使用这个密匙, Attack AT DAWN (黎明时攻击)就会被加密为Tpptad TP ITVH。
请实现下述接口,通过指定的密匙和明文得到密文。
数据范围:1 \le n \le 100 \1≤n≤100 ,保证输入的字符串中仅包含小写字母
输入描述:
先输入key和要加密的字符串
输出描述:
返回加密后的字符串
示例1
输入:
nihao
ni
复制
输出:
le

while True:
    try:
        m=input()
        n=input()
        l=''
        for i in range(26):
            l+=chr(97+i)
        res=''
        for i in m:
            if i in res:
                continue
            else:
                res+=i
        for i in l:
            if i in res:
                continue
            else:
                res+=i

        res_2=''
        for i in n:
            res_2+=res[ord(i)-97]
        print(res_2)
    except:
        break

8、HJ105 记负均正II

解题思路:
1、此题是不定量输入,所以借用EOFError进行文件结束符的判断
2、此题是只会输入整型,所以使用int
3、round(data,1) 代表保留小数点1位

题目
题解(117)
讨论(311)
排行
面经new
简单 通过率:28.38% 时间限制:1秒 空间限制:32M
知识点
数组
思维
warning 校招时部分企业笔试将禁止编程题跳出页面,为提前适应,练习时请使用在线自测,而非本地IDE。
描述
输入 n 个整型数,统计其中的负数个数并求所有非负数的平均值,结果保留一位小数,如果没有非负数,则平均值为0
本题有多组输入数据,输入到文件末尾。
数据范围:1 \le n \le 50000 \1≤n≤50000 ,其中每个数都满足 |val| \le 10^{6} \∣val∣≤10
6
输入描述:
输入任意个整数,每行输入一个。
输出描述:
输出负数个数以及所有非负数的平均值
示例1
输入:
-13
-4
-7
复制
输出:
3
0.0

n_l=[]
p_l=[]
while 1:
    try:
        n=int(input())
        if n<0:
            n_l.append(n)
        else:
            p_l.append(n)
    except EOFError:
        print(len(n_l))
        print(round((sum(p_l)/len(p_l)),1) if len(p_l) else '0.0')
        break

二、牛客-中等类

1、HJ41 称砝码-zip()、列表*数字、集合遍历、集合增加元素

zip:将可迭代对象组成元组,将元组组成的元素返回。优势是节省资源。若存在长和短的,会针对短的列表进行组合。
列表[1]*4>>>[1,1,1,1]
在遍历集合,出现集合长度变更,易出现报错:Set changed size during iteration,可转换为list
集合增加元素,用add

描述
现有n种砝码,重量互不相等,分别为 m1,m2,m3…mn ;
每种砝码对应的数量为 x1,x2,x3…xn 。现在要用这些砝码去称物体的重量(放在同一侧),问能称出多少种不同的重量。
注:
称重重量包括 0
数据范围:每组输入数据满足 1 \le n \le 10 \1≤n≤10 , 1 \le m_i \le 2000 \1≤m i≤2000 , 1 \le x_i \le 10 \1≤x i
≤10
输入描述:
对于每组测试数据:
第一行:n — 砝码的种数(范围[1,10])
第二行:m1 m2 m3 … mn — 每种砝码的重量(范围[1,2000])
第三行:x1 x2 x3 … xn — 每种砝码对应的数量(范围[1,10])
输出描述:
利用给定的砝码可以称出的不同的重量数
示例1
输入:
2
1 2
2 1
复制
输出:
5
复制
说明:
可以表示出0,1,2,3,4五种重量。

while True:
    try:
        m=int(input())
        lst_1=list(map(int,input().split()))
        lst_2=list(map(int,input().split()))
        lst=[]
        for i in zip(lst_1,lst_2):
            lst+=[i[0]]*i[1]
        weight={0}
        for i in lst:
            for j in list(weight):
                weight.add(i+j)
        print(len(weight))
    except:
        break

2、HJ17 坐标移动–异常捕获、res[0,0]存储元素、长度判断

解题关键:
遍历列表时对首字母判断
首字母后面的用切片,可能存在非数字时,捕获异常

描述
开发一个坐标计算工具, A表示向左移动,D表示向右移动,W表示向上移动,S表示向下移动。从(0,0)点开始移动,从输入字符串里面读取一些坐标,并将最终输入结果输出到输出文件里面。
输入:
合法坐标为A(或者D或者W或者S) + 数字(两位以内)
坐标之间以;分隔。
非法坐标点需要进行丢弃。如AA10; A1A; python在同一行内输入两个正整数 python一行输入两个字符串_字符串; YAD; 等。
下面是一个简单的例子 如:
A10;S20;W10;D30;X;A1A;B10A11;;A10;
处理过程:
起点(0,0)
A10 = (-10,0)
S20 = (-10,-20)
W10 = (-10,-10)
D30 = (20,-10)
x = 无效
A1A = 无效
B10A11 = 无效
一个空 不影响
A10 = (10,-10)
结果 (10, -10)
数据范围:每组输入的字符串长度满足 1\le n \le 10000 \1≤n≤10000 ,坐标保证满足 -2^{31} \le x,y \le 2^{31}-1 \−2 31≤x,y≤2 31 −1 ,且数字部分仅含正数
输入描述:
一行字符串
输出描述:
最终坐标,以逗号分隔
示例1
输入:
A10;S20;W10;D30;X;A1A;B10A11;;A10;
复制
输出:
10,-10

while True:
    try:
        input_lst=input().split(';')
        res=[0,0]
        for i in input_lst:
            if 2<=len(i)<=3:
                j = i[0]
                try:
                    if j =='A':
                        res[0]-=int(i[1:])
                    elif j=='D':
                        res[0]+=int(i[1:])
                    elif j=='W':
                        res[1]+=int(i[1:])
                    elif j=='S':
                        res[1]-=int(i[1:])
                except ValueError:
                    continue
        print(','.join(map(str,res)))
    except:
        break

3、HJ63 DNA序列–一段长度字符串输出指定长度时的遍历妙用、count

解题关键:
range(len(s)-length+1)
s.count(“G”,i,i+length)
i一定会遍历到最后,所以取目标值需设定m接收i的值。

描述
一个 DNA 序列由 A/C/G/T 四个字母的排列组合组成。 G 和 C 的比例(定义为 GC-Ratio )是序列中 G 和 C 两个字母的总的出现次数除以总的字母数目(也就是序列长度)。在基因工程中,这个比例非常重要。因为高的 GC-Ratio 可能是基因的起始点。
给定一个很长的 DNA 序列,以及限定的子串长度 N ,请帮助研究人员在给出的 DNA 序列中从左往右找出 GC-Ratio 最高且长度为 N 的第一个子串。
DNA序列为 ACGT 的子串有: ACG , CG , CGT 等等,但是没有 AGT , CT 等等
数据范围:字符串长度满足 1 \le n \le 1000 \1≤n≤1000 ,输入的字符串只包含 A/C/G/T 字母
输入描述:
输入一个string型基因序列,和int型子串的长度
输出描述:
找出GC比例最高的子串,如果有多个则输出第一个的子串
示例1
输入:
ACGT
2
复制
输出:
CG
复制
说明:
ACGT长度为2的子串有AC,CG,GT3个,其中AC和GT2个的GC-Ratio都为0.5,CG为1,故输出CG

s=input()
length=int(input())
max=0
m=0
for i in range(len(s)-length+1):
    gc_max=s.count("G",i,i+length)+s.count("C",i,i+length)
    if gc_max>max:
        max=gc_max
        m=i
print(s[m:m+length])

4、HJ92 在字符串中找出连续最长的数字串–isalpha()、replace、

解题思路:
将字母都转换成空格,在切片判断长度。
将字母替换成空格,无需循环,直接替换即可。
replace():產生新字符串,在下一次調用時不改變原字符串

描述
输入一个字符串,返回其最长的数字子串,以及其长度。若有多个最长的数字子串,则将它们全部输出(按原字符串的相对位置)
本题含有多组样例输入。
数据范围:字符串长度 1 \le n \le 200 \1≤n≤200 , 保证每组输入都至少含有一个数字
输入描述:
输入一个字符串。1<=len(字符串)<=200
输出描述:
输出字符串中最长的数字字符串和它的长度,中间用逗号间隔。如果有相同长度的串,则要一块儿输出(中间不要输出空格)。
示例1
输入:
abcd12345ed125ss123058789
a8a72a6a5yy98y65ee1r2
复制
输出:
123058789,9
729865,2
复制
说明:
样例一最长的数字子串为123058789,长度为9
样例二最长的数字子串有72,98,65,长度都为2

while True:
    try:
        s=input()
        for i in s:
            if i.isalpha():
                s=s.replace(i, " ")
        s2=s.split()
        lenth_max=0
        for i in s2:
            if len(i)>lenth_max:
                lenth_max=len(i) 
        res=''
        for i in s2:
            if len(i)==lenth_max:
                res+=i 
        print(res+','+str(lenth_max))
    except:
        break

5、HJ32 密码截取–回文子串

解题思路:回文子串,range(i,len(s)-1)–range(i+1,len(s))。还有将两者进行对比。

描述
Catcher是MCA国的情报员,他工作时发现敌国会用一些对称的密码进行通信,比如像这些ABBA,ABA,A,123321,但是他们有时会在开始或结束时加入一些无关的字符以防止别国破解。比如进行下列变化 ABBA->12ABBA,ABA->ABAKK,123321->51233214 。因为截获的串太长了,而且存在多种可能的情况(abaaab可看作是aba,或baaab的加密形式),Cathcer的工作量实在是太大了,他只能向电脑高手求助,你能帮Catcher找出最长的有效密码串吗?
数据范围:字符串长度满足 1 \le n \le 2500 \1≤n≤2500
输入描述:
输入一个字符串(字符串的长度不超过2500)
输出描述:
返回有效密码串的最大长度
示例1
输入:
ABBA
复制
输出:
4

while True:
    try:
        s=input()
        max_s=[]
        for i in range(len(s)-1):
            for j in range(i+1,len(s)):
                if s[i]==s[j] and s[i+1:j]==s[j-1:i:-1]:
                    max_s.append(len(s[i:j+1]))
        print(max(max_s))
    except:
        break

6、HJ33 整数与IP地址间的转换-bin()、int(X,2)、‘0’*(8-len(s))

解题思路:
1、bin():可将10进制转为2进制,但开头会有0b,需切片去除。结果是字符串。
2、int(X,2):当有2个参数时,第一个必须为字符串。
3、当变成二进制,需补齐8位。‘0’*(8-len(s))
4、输出方式,join可使列表转字符串。

描述
原理:ip地址的每段可以看成是一个0-255的整数,把每段拆分成一个二进制形式组合起来,然后把这个二进制数转变成
一个长整数。
举例:一个ip地址为10.0.3.193
每段数字 相对应的二进制数
10 00001010
0 00000000
3 00000011
193 11000001
组合起来即为:00001010 00000000 00000011 11000001,转换为10进制数就是:167773121,即该IP地址转换后的数字就是它了。
数据范围:保证输入的是合法的 IP 序列
输入描述:
输入
1 输入IP地址
2 输入10进制型的IP地址
输出描述:
输出
1 输出转换成10进制的IP地址
2 输出转换后的IP地址
示例1
输入:
10.0.3.193
167969729
复制
输出:
167773121
10.3.3.193

ip_num=list(map(int,input().split('.')))
num=bin(int(input()))[2:]
# 切片获取数字,转换成2进制,相加,转换成10进制
sum_ip_num=''
for i in ip_num:
    b=bin(i)[2:]
    sum_ip_num+='0'*(8-len(b))+b if len(b)<8 else b
print(int(sum_ip_num,2))
# 转成2进制,长度补齐,分成8份,再转成10进制
num='0'*(32-len(num))+num if len(num)<32 else num
res_num_to_ip=[]
for i in range(4):
    num_to_ip=int(num[i*8:(i+1)*8],2)
    res_num_to_ip.append(str(num_to_ip))
print('.'.join(res_num_to_ip))

7、HJ20 密码验证合格程序–return 0、ord判断类型大于2、相同子串判断

解题思路:
1、多条件判断,可用函数,结果设置return
2、字符串类型大于2,可用ord进行大小写、数字的存在判断
3、字符串内不能出现长度>2相同子串,用len(s.split(s[i:i+3]))>2判断

描述
密码要求:
1.长度超过8位
2.包括大小写字母.数字.其它符号,以上四种至少三种
3.不能有长度大于2的包含公共元素的子串重复 (注:其他符号不含空格或换行)
数据范围:输入的字符串长度满足 1 \le n \le 100 \1≤n≤100
输入描述:
一组字符串。
输出描述:
如果符合要求输出:OK,否则输出NG
示例1
输入:
021Abc9000
021Abc9Abc1
021ABC9000
021$bc9000
复制
输出:
OK
NG
NG
OK

def check(s):
    if len(s)<=8:
        return 0
    a,b,c,d=0,0,0,0
    for i in s:
        if ord('a')<=ord(i)<=ord('z'):
            a=1
        elif ord('A')<=ord(i)<=ord('Z'):
            b=1
        elif ord('0')<=ord(i)<=ord('9'):
            c=1
        else:
            d=1
    if a+b+c+d<3:
        return 0
    for i in range(len(s)-3):
        length=s.split(s[i:i+3])
        if len(length)>2:
            return 0
    return 1
while 1:
    try:
        s=input()
        print("OK" if check(s) else "NG")
    except:
        break

8、HJ69 矩阵乘法–二维矩阵,不换行输出

解题思路:
矩阵乘法的原理MXN和NXM的矩阵,最终得到MXM的矩阵。
二维矩阵:列表嵌套子列表,子列表内是每行的元素
初始化最终的数组:[[0 for i in range(z)] for j in range(x)]
二维数组相乘:通过for层层遍历,记住:x>z>y,所以按此顺序遍历
输出方式:print默认是换行的,若想不换行,可用print(x,end=’ ')代替。

描述
如果A是个x行y列的矩阵,B是个y行z列的矩阵,把A和B相乘,其结果将是另一个x行z列的矩阵C。这个矩阵的每个元素是由下面的公式决定的
矩阵的大小不超过100*100
输入描述:
第一行包含一个正整数x,代表第一个矩阵的行数
第二行包含一个正整数y,代表第一个矩阵的列数和第二个矩阵的行数
第三行包含一个正整数z,代表第二个矩阵的列数
之后x行,每行y个整数,代表第一个矩阵的值
之后y行,每行z个整数,代表第二个矩阵的值
输出描述:
对于每组输入数据,输出x行,每行z个整数,代表两个矩阵相乘的结果
示例1
输入:
2
3
2
1 2 3
3 2 1
1 2
2 1
3 3
复制
输出:
14 13
10 11
复制
说明:
1 2 3
3 2 1
乘以
1 2
2 1
3 3
等于
14 13
10 11

while True:
    try:
        x=int(input())
        y=int(input())
        z=int(input())
        a=[]
        b=[]
        for i in range(x):
            a.append(list(map(int,input().split()))) # 子列表代表每行的元素,有多少个子列表,代表拥有几列
        for j in range(y):
            b.append(list(map(int,input().split())))
        R=[[0 for i in range(z)] for j in range(x)]  # 初始化子列表
        for i in range(x):
            for j in range(z):
                for k in range(y):
                    R[i][j]+= a[i][k]*b[k][j]
        for i in range(x):
            for j in range(z):
                print(R[i][j],end=' ')
            print(' ')
    except:
        break

9、HJ67 24点游戏算法–permutations

使用permutations,再加symbols的多重循环

描述
给出4个1-10的数字,通过加减乘除运算,得到数字为24就算胜利,除法指实数除法运算,运算符仅允许出现在两个数字之间,本题对数字选取顺序无要求,但每个数字仅允许使用一次,且需考虑括号运算
此题允许数字重复,如3 3 4 4为合法输入,此输入一共有两个3,但是每个数字只允许使用一次,则运算过程中两个3都被选取并进行对应的计算操作。
输入描述:
读入4个[1,10]的整数,数字允许重复,测试用例保证无异常数字。
输出描述:
对于每组案例,输出一行表示能否得到24点,能输出true,不能输出false
示例1
输入:
7 2 1 10
复制
输出:
true

from itertools import permutations
lst1=list(map(int,input().split()))
result=[i for i in permutations(lst1,4)]
lst=[]
symbols=['+','-','*','/']
for a,b,c,d in result:
    for s1 in symbols:
        for s2 in symbols:
            for s3 in symbols:
                if s1+s2+s3=="+++" or s1+s2+s3=="***":
                    express=['{0}{1}{2}{3}{4}{5}{6}'.format(a,s1,b,s2,c,s3,d)]
                else: # 双括号
                    express=['({0}{1}{2}){3}({4}{5}{6})'.format(a,s1,b,s2,c,s3,d),
                            '({0}{1}({2}{3}{4})){5}{6}'.format(a,s1,b,s2,c,s3,d),
                            '{0}{1}({2}{3}({4}{5}{6}))'.format(a,s1,b,s2,c,s3,d),
                            '(({0}{1}{2}){3}{4}){5}{6}'.format(a,s1,b,s2,c,s3,d),
                            '{0}{1}(({2}{3}{4}){5}{6})'.format(a,s1,b,s2,c,s3,d),]
                for e in express:
                    try:
                        if eval(e)==24:
                            lst.append(e)
                    except ZeroDivisionError:
                        pass
if lst:
    print('true')
else:
    print('false')

10、HJ103 Redraiment的走法–动态规划、reversed

解题思路:
1、此题明显地用到了动态规划,使用迭代方式,降低时间复杂度。
2、reversed:反转的迭代生成器。

描述
Redraiment是走梅花桩的高手。Redraiment可以选择任意一个起点,从前到后,但只能从低处往高处的桩子走。他希望走的步数最多,你能替Redraiment研究他最多走的步数吗?
数据范围:每组数据长度满足 1 \le n \le 200 \1≤n≤200 , 数据大小满足 1 \le val \le 350 \1≤val≤350
输入描述:
数据共2行,第1行先输入数组的个数,第2行再输入梅花桩的高度
输出描述:
输出一个结果
示例1
输入:
6
2 5 1 5 4 5
复制
输出:
3

n=int(input())
s=[int(i) for i in input().split()]
L=[1]*n 
for i in reversed(range(n)):
    for j in range(i+1,n):
        if s[j]>s[i]: # 注意这里的前提条件,若未进入循环,则为1.
            L[i]=max(L[i],L[j]+1) # 拿L[i]和L[j]+1相比,如果大于1,就更新值。
print(max(L))

11、HJ82 将真分数分解为埃及分数----while a、range步长

问题点:1、会列举出所有能被b整除的值,总值大于原值!解决办法:1、使用break可及时退出for循环,但此时a大于1;2、添加while a
易错点:a,b转为int;b/i默认保留1位小数,需用int去掉。
解题思路:相当于通分的逆转过程;每次循环结束需a=a-i,保证值不变

描述
分子为1的分数称为埃及分数。现输入一个真分数(分子比分母小的分数,叫做真分数),请将该分数分解为埃及分数。如:8/11 = 1/2+1/5+1/55+1/110。
注:真分数指分子小于分母的分数,分子和分母有可能gcd不为1!
如有多个解,请输出任意一个。
输入描述:
输入一个真分数,String型
输出描述:
输出分解后的string
示例1
输入:
8/11
2/4
复制
输出:
1/2+1/5+1/55+1/110
1/3+1/6
复制
说明:
第二个样例直接输出1/2也是可以的

a,b=input().split('/')
a=int(a)*10
b=int(b)*10
res=[]
while a:
    for i in range(a,0,-1):
            if b%i==0:
                res.append('1'+'/'+str(int(b/i)))
                a=a-i
                break
print('+'.join(res))

12、HJ74 参数解析----字符串转换

解题思路:
直接将空格替换为换行符,方便输出
用flag判断是否遇到",若遇到,就将flag值变更,顺便跳过一个i值,跳过"
在flag范围内的,遇到\n就换成空格
注意:最后一个值后面没有\n

描述
在命令行输入如下命令:
xcopy /s c:\ d:\e,
各个参数如下:
参数1:命令字xcopy
参数2:字符串/s
参数3:字符串c:\
参数4: 字符串d:\e
请编写一个参数解析程序,实现将命令行各个参数解析出来。
解析规则:
1.参数分隔符为空格
2.对于用""包含起来的参数,如果中间有空格,不能解析为多个参数。比如在命令行输入xcopy /s “C:\program files” "d:“时,参数仍然是4个,第3个参数应该是字符串C:\program files,而不是C:\program,注意输出参数时,需要将”"去掉,引号不存在嵌套情况。
3.参数不定长
4.输入由用例保证,不会出现不符合要求的输入
数据范围:字符串长度:1\le s\le 1000\1≤s≤1000
进阶:时间复杂度:O(n)\O(n) ,空间复杂度:O(n)\O(n)
输入描述:
输入一行字符串,可以有空格
输出描述:
输出参数个数,分解后的参数,每个参数都独占一行
示例1
输入:
xcopy /s c:\ d:\e
复制
输出:
4
xcopy
/s
c:\
d:\e

s=input()
s=s.replace(' ','\n')
e=''
flag=False
for i in s:
    if i=='"':
        flag= not flag
    elif flag==True and i=='\n':
        e+=' '
    else:
        e+=i
b=e.count('\n')+1
print(b)
print(e)

13、HJ24 合唱队

解题思路:
求出向左、向右的各元素最长递增子序列最长长度
终值=向左长度+向右长度-1 # 在遍历左值时开始计算
关键点:
将列表[::-1]反向传入,再将结果翻转
左向结果列表与右向结果列表相加减一成为新列表,再对新列表求最大值

描述
N 位同学站成一排,音乐老师要请最少的同学出列,使得剩下的 K 位同学排成合唱队形。
通俗来说,能找到一个同学,他的两边的同学身高都依次严格降低的队形就是合唱队形。
例子:
123 124 125 123 121 是一个合唱队形
123 123 124 122不是合唱队形,因为前两名同学身高相等,不符合要求
123 122 121 122不是合唱队形,因为找不到一个同学,他的两侧同学身高递减。
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
注意:不允许改变队列元素的先后顺序 且 不要求最高同学左右人数必须相等
数据范围: 1 \le n \le 3000 \1≤n≤3000
输入描述:
用例两行数据,第一行是同学的总数 N ,第二行是 N 位同学的身高,以空格隔开
输出描述:
最少需要几位同学出列
示例1
输入:
8
186 186 150 200 160 130 197 200
复制
输出:
4

def max_l(queue):
    dp=[1]*len(queue)
    for i in reversed(range(len(queue))):
        for j in range(i+1,len(queue)):
            if queue[i]>queue[j]:
                dp[i]=max(dp[i],dp[j]+1)
    return dp
n=int(input())
queue=[int(i) for i in input().split()]
if n==len(queue):
    left=max_l(queue)
    right=max_l(queue[::-1])[::-1] # 关键点
    max_=max([left[i]+right[i]-1 for i in range(len(left))]) #
    print(n-max_)

14、HJ52 计算字符串的编辑距离–动态规划

解题思路:
求通过增删改到另一个元素的最小值,其实是冬天规划问题的演变
注意点:m为0,dp[0][i]=i;n为0,dp[j][0]=j;
动态规划,其实关键点就是前一位状态到达的方式,再加上最后一位0或者1的变化。
如甲变成乙
am–>an,是从a[i-1][j-1]+1产生的
anf–>af,是从a[i-1][j]+0产生的
af–>amf,是从a[i][j-1]+0产生的
所以当值相等,则跳过。当值不相等,则从三种情况选取最小值,再+1。

描述
Levenshtein 距离,又称编辑距离,指的是两个字符串之间,由一个转换成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。编辑距离的算法是首先由俄国科学家 Levenshtein 提出的,故又叫 Levenshtein Distance 。
例如:
字符串A: abcdefg
字符串B: abcdef
通过增加或是删掉字符 ”g” 的方式达到目的。这两种方案都需要一次操作。把这个操作所需要的次数定义为两个字符串的距离。
要求:
给定任意两个字符串,写出一个算法计算它们的编辑距离。
数据范围:给定的字符串长度满足 1 \le len(str) \le 1000 \1≤len(str)≤1000
输入描述:
每组用例一共2行,为输入的两个字符串
输出描述:
每组用例输出一行,代表字符串的距离
示例1
输入:
abcdefg
abcdef
复制
输出:
1

while 1:
    try:
        str1=input()
        str2=input()
        m=len(str1)
        n=len(str2)
        dp =[[1 for i in range(n+1)] for j in range(m+1)] # 为什么要+1?需添加m为0或n为0的情况,再对应操作。dp[n][m]就是最终结果
        for i in range(n+1):
            dp[0][i]=i # 若第二个字符串长度为0,则变成第一个的距离是i
        for j in range(m+1):
            dp[j][0]=j # 若第一个字符串长度为0,则变成第二个的举例是j
        for i in range(1,m+1): # 
            for j in range(1,n+1):
                if str1[i-1]==str2[j-1]: # 当两个字母相同,跳过,步数不增加
                    dp[i][j]=dp[i-1][j-1]
                else:
                    dp[i][j]=min(dp[i-1][j-1],dp[i][j-1],dp[i-1][j])+1 # 如果两个字母不同,则有三种方式(删除、插入、替换)。选择最小的前状态,再加1个步数。
        print(dp[m][n])
    except:
        break

三、牛客-较难类

1、HJ3 明明的随机数–set

解题思路:
list保存数据,使用set去重,再使用sorted排序
注意:sorted排列“123”,“6”,先根据1来排,所以"123"在"6"前面。

描述
明明生成了NN个1到500之间的随机整数。请你删去其中重复的数字,即相同的数字只保留一个,把其余相同的数去掉,然后再把这些数从小到大排序,按照排好的顺序输出。
数据范围: 1 \le n \le 1000 \1≤n≤1000 ,输入的数字大小满足 1 \le val \le 500 \1≤val≤500
输入描述:
第一行先输入随机整数的个数 N 。 接下来的 N 行每行输入一个整数,代表明明生成的随机数。 具体格式可以参考下面的"示例"。
输出描述:
输出多行,表示输入数据处理后的结果
示例1
输入:
3
2
2
1
复制
输出:
1
2
复制
说明:
输入解释:
第一个数字是3,也即这个小样例的N=3,说明用计算机生成了3个1到500之间的随机整数,接下来每行一个随机数字,共3行,也即这3个随机数字为:
2
2
1
所以样例的输出为:
1
2

n=int(input())
lst=[]
for i in range(n):
    lst.append(int(input()))
a=sorted(set(lst))
for i in a:
    print(i)

2、HJ42 学英语

分为3层:c个“个十百million”,b个“个十百thousand”,a个“个十百”,按照3个层级进行处理,且顺序为c/b/a
函数嵌套,判断是否大于100,若有,则进入<1000函数;若没有,则进入下一层<100函数
num1 num2 列表下标与数值对应
注意:if num !=0: result.append(num1[num]),一定要加此判断,否则末尾会多一个zero。

描述
Jessi初学英语,为了快速读出一串数字,编写程序将数字转换成英文:
具体规则如下:
1.在英语读法中三位数字看成一整体,后面再加一个计数单位。从最右边往左数,三位一单位,例如12,345 等
2.每三位数后记得带上计数单位 分别是thousand, million, billion.
3.公式:百万以下千以上的数 X thousand X, 10亿以下百万以上的数:X million X thousand X, 10 亿以上的数:X billion X million X thousand X. 每个X分别代表三位数或两位数或一位数。
4.在英式英语中百位数和十位数之间要加and,美式英语中则会省略,我们这个题目采用加上and,百分位为零的话,这道题目我们省略and
下面再看几个数字例句:
22: twenty two
100: one hundred
145: one hundred and forty five
1,234: one thousand two hundred and thirty four
8,088: eight thousand (and) eighty eight (注:这个and可加可不加,这个题目我们选择不加)
486,669: four hundred and eighty six thousand six hundred and sixty nine
1,652,510: one million six hundred and fifty two thousand five hundred and ten
说明:
数字为正整数,不考虑小数,转化结果为英文小写;
保证输入的数据合法
关键字提示:and,billion,million,thousand,hundred。
数据范围:1 \le n \le 2000000 \1≤n≤2000000
输入描述:
输入一个long型整数
输出描述:
输出相应的英文写法
示例1
输入:
22
复制
输出:
twenty two

num1=['zero','one','two','three','four','five','six',
       'seven','eight','nine','ten','eleven','twelve',
       'thirteen','fourteen','fifteen','sixteen',
       'seventeen','eighteen','nineteen']
num2=['','','twenty','thirty','forty','fifty','sixty',
       'seventy','eighty','ninety']
def less_than_100(num):
    if num <20:
        result.append(num1[num])
    if num>19:
        s=num//10
        result.append(num2[s])
        num=num-s*10
        if num !=0:
            result.append(num1[num])
def less_than_1000(num):
    if num >=100:
        s=num//100
        result.append(num1[s])
        result.append('hundred')
        num=num-s*100
        if num!=0:
            result.append('and')
    if num <100 and num !=0:
        less_than_100(num)
num = int(input())
result=[]
a=num%1000 # 若出现111,可直接处理
b=(num//1000)%1000 # 若出现1,111 可进行处理
c=num//1000000 # 若出现1,111,111 可进行处理
if c>0:
    less_than_1000(c)
    result.append('million')
if b>0:
    less_than_1000(b)
    result.append('thousand')
if a>0:
    less_than_1000(a)
print(' '.join(result))

3、HJ68 成绩排序

解题思路:
1、字典存值,sorted排序,方法不可行:键不可相同,会出现相同人名。
2、列表嵌套元组,对元组的第二个值lst.sort(lambda x:x[1],reverse=flag)

描述
给定一些同学的信息(名字,成绩)序列,请你将他们的信息按照成绩从高到低或从低到高的排列,相同成绩
都按先录入排列在前的规则处理。
例示:
jack 70
peter 96
Tom 70
smith 67
从高到低 成绩
peter 96
jack 70
Tom 70
smith 67
从低到高
smith 67
jack 70
Tom 70
peter 96
注:0代表从高到低,1代表从低到高
数据范围:人数:1\le n \le 200\1≤n≤200
进阶:时间复杂度:O(nlogn)\O(nlogn) ,空间复杂度:O(n)\O(n)
输入描述:
第一行输入要排序的人的个数n,第二行输入一个整数表示排序的方式,之后n行分别输入他们的名字和成绩,以一个空格隔开
输出描述:
按照指定方式输出名字和成绩,名字和成绩之间以一个空格隔开
示例1
输入:
3
0
fang 90
yang 50
ning 70
复制
输出:
fang 90
ning 70
yang 50

num=int(input())
if input()=='0':
    flag=True
else:
    flag=False
lst=[]
for i in range(num):
    name,score=input().split()
    lst.append((name,int(score))) # 列表内添加元组
lst.sort(key=lambda x:x[1],reverse=flag)
for i in lst:
    print(*i)

4、HJ89 24点运算–dict(zip())、字母转数字并运用、return

解题思路:
1、24点运算,可使用permutions,已是第三次解题。
2、关于JQKA转为数字并在输出时仍为字母,可用dict(zip())
3、当想结束函数,可直接return

描述
计算24点是一种扑克牌益智游戏,随机抽出4张扑克牌,通过加(+),减(-),乘(), 除(/)四种运算法则计算得到整数24,本问题中,扑克牌通过如下字符或者字符串表示,其中,小写joker表示小王,大写JOKER表示大王:
3 4 5 6 7 8 9 10 J Q K A 2 joker JOKER
本程序要求实现:输入4张牌,输出一个算式,算式的结果为24点。
详细说明:
1.运算只考虑加减乘除运算,没有阶乘等特殊运算符号,没有括号,友情提醒,整数除法要当心,是属于整除,比如2/3=0,3/2=1;
2.牌面210对应的权值为210, J、Q、K、A权值分别为为11、12、13、1;
3.输入4张牌为字符串形式,以一个空格隔开,首尾无空格;如果输入的4张牌中包含大小王,则输出字符串“ERROR”,表示无法运算;
4.输出的算式格式为4张牌通过±
/四个运算符相连,中间无空格,4张牌出现顺序任意,只要结果正确;
5.输出算式的运算顺序从左至右,不包含括号,如1+2+34的结果为24,2 A 9 A不能变为(2+1)(9-1)=24
6.如果存在多种算式都能计算得出24,只需输出一种即可,如果无法得出24,则输出“NONE”表示无解。
7.因为都是扑克牌,不存在单个牌为0的情况,且没有括号运算,除数(即分母)的数字不可能为0
数据范围:一行由4张牌组成的字符串
输入描述:
输入4张牌为字符串形式,以一个空格隔开,首尾无空格;
输出描述:
输出怎么运算得到24,如果无法得出24,则输出“NONE”表示无解,如果输入的4张牌中包含大小王,则输出字符串“ERROR”,表示无法运算;
示例1
输入:
A A A A
复制
输出:
NONE
复制
说明:
不能实现
示例2
输入:
4 2 K A
复制
输出:
K-A4/2
复制
说明:
A+K
2-4也是一种答案,输出任意一种即可

from itertools import permutations
s1=['A','2','3','4','5','6','7','8','9','10','J','Q','K']
s2=range(1,14)
new_dict=dict(zip(s1,s2))
lst=input().split()
def express(lst):
    if 'joker' in lst or 'JOKER' in lst:
        print('ERROR')
        return
    res=[i for i in permutations(lst,4)]
    symbols = ['+', '-', '*', '/']
    lst1 = []
    for a, b, c, d in res:
        for s1 in symbols:
            for s2 in symbols:
                for s3 in symbols:
                    express = ['(({0}{1}{2}){3}{4}){5}{6}'.format(new_dict[a], s1, new_dict[b], s2, new_dict[c], s3, new_dict[d])]
                  for e in express:
                        try:
                            if eval(e) == 24:
                                lst1.append(a+s1+b+s2+c+s3+d)
                        except ZeroDivisionError:
                            continue
    if len(lst1)>0:
        print(lst1[0])
        return
    else:
        print('NONE')
        return 
express(lst)

5、HJ95 人民币转换

解题思路:
1、此题和学英语类似,通过对值进行3种情况考虑:亿、万前的数值,万后的数值
2、使用函数嵌套:within10000-with1000-with100,在小于某值时,需添加零
3、小数部分,按照顺序取两个列表对应的值。注意:需过滤为零的情况
4、将零零情况过滤
5、将开头零零情况过滤

描述
考试题目和要点:
1、中文大写金额数字前应标明“人民币”字样。中文大写金额数字应用壹、贰、叁、肆、伍、陆、柒、捌、玖、拾、佰、仟、万、亿、元、角、分、零、整等字样填写。
2、中文大写金额数字到“元”为止的,在“元”之后,应写“整字,如532.00应写成“人民币伍佰叁拾贰元整”。在”角“和”分“后面不写”整字。
3、阿拉伯数字中间有“0”时,中文大写要写“零”字,阿拉伯数字中间连续有几个“0”时,中文大写金额中间只写一个“零”字,如6007.14,应写成“人民币陆仟零柒元壹角肆分“。
4、10应写作“拾”,100应写作“壹佰”。例如,1010.00应写作“人民币壹仟零拾元整”,110.00应写作“人民币壹佰拾元整”
5、十万以上的数字接千不用加“零”,例如,30105000.00应写作“人民币叁仟零拾万伍仟元整”
输入描述:
输入一个double数
输出描述:
输出人民币格式
示例1
输入:
151121.15
复制
输出:
人民币拾伍万壹仟壹佰贰拾壹元壹角伍分

n='零,壹,贰,叁,肆,伍,陆,柒,捌,玖,拾,拾壹,拾贰,拾叁,拾肆,拾伍,拾陆,拾柒,拾捌,拾玖'.split(',') # 学习点,不用手打指定的列表格式
q='角,分'.split(',')
# 按照数字,区分100,1000,10000
# 小于100的方法逻辑:1、判断是否小于20;2、判断是否个位数,得加0;3、若为几十,则取整加‘拾’;4、若为几十几,则取余加剩下的数。
def within100(num):
    tmp=[]
    if num <20:
        if num <10:
            tmp.append('零') # 此处注意,小于100的个位数,就代表要取整
        tmp.append(n[num])
    else:
        tmp.append(n[num//10]) # //代表取整,就不用int再进行转换了
        tmp.append('拾')
        if num%10 !=0:
            tmp.append(n[num%10])
    return tmp
def within1000(num): # 1000以下,若遇到100以下,如10080,则考虑零的情况
    tmp=[]
    if num<100:
        tmp.append('零')
        tmp+=within100(num)
    else:
        tmp.append(n[num//100])
        tmp.append('佰')
        if num%100!=0:
            if num%100 <10:
                tmp.append('零')
            tmp+=within100(num%100)
    return tmp
def within10000(num):
    tmp=[]
    if num<1000:
        tmp.append('零')
        tmp+=within1000(num)
    else:
        tmp.append(n[num//1000])
        tmp.append('仟')
        if num%1000!=0:
            if num%1000 <100:
                tmp.append('零')
            tmp+=within1000(num%1000)
    return tmp
def small(num):# 方法学习,遍历获取两个列表中的值
    tmp=[]
    for i in range(len(num)):
        if int(num[i])!=0:
            tmp.append(n[int(num[i])])
            tmp.append(q[i])
    return tmp

while 1:
    try:
        z1,z2=input().split('.')
        z1=int(z1)
    except:
        break
    else:
        # 整数部门
        fin=[]
        a=z1//100000000 # 为何这里从亿开始
        b=(z1//10000)%10000 # 获取万前面的四位数
        c=z1%10000 # 获取万后面的四位数
        if a>0:
            fin+=within10000(a)
            fin.append('亿') # 无法处理万亿数字
        if b>0:
            fin+=within10000(b)
            fin.append('万')
        if c>0:
            fin+=within10000(c)

        if len(fin)>0: # 排除整数部分为0的部分
            fin.append('元')
        if int(z2)==0:
            fin.append('整')
        else:
            fin+=small(z2)

        final="".join(fin)
        while '零零' in final:
            final=final.replace("零零", "零")
        final=final.strip("零")  # 去掉头尾的零
        print("人民币"+final)

6、HJ93 数组分组–递归方式学习、sum

解题思路:
1、分为3组,将other组逐个添加到three、five中
2、难点:other中的值添加到前两数组后,如何判断sum
3、学习点:sum(three)----直接对列表求和
4、学习点:other[:1]

描述
输入int型数组,询问该数组能否分成两组,使得两组中各元素加起来的和相等,并且,所有5的倍数必须在其中一个组中,所有3的倍数在另一个组中(不包括5的倍数),不是5的倍数也不是3的倍数能放在任意一组,可以将数组分为空数组,能满足以上条件,输出true;不满足时输出false。
数据范围:每个数组大小满足 1 \le n \le 50 \1≤n≤50 ,输入的数据大小满足 |val| \le 500 \∣val∣≤500
输入描述:
第一行是数据个数,第二行是输入的数据
输出描述:
返回true或者false
示例1
输入:
4
1 5 -5 1
复制
输出:
true
复制
说明:
第一组:5 -5 1
第二组:1

def dfs(three, five, other):
    if not other:
        if sum(three) == sum(five):# 学习点
            return True
        else:
            return False
    if dfs(three + other[:1], five, other[1:]):  # 学习点
        return True
    if dfs(three, five + other[:1], other[1:]):
        return True


while 1:
    try:
        n, num = int(input()), list(map(int, input().split()))
        three, five, other = [], [], []
        for i in num:
            if i % 3 == 0:
                three.append(i)
            elif i % 5 == 0:
                five.append(i)
            else:
                other.append(i)
        if dfs(three, five, other):
            print('true')
        else:
            print('false')
    except:
        break

7、HJ39 判断两个IP是否属于同一子网

解题思路:
易错点:if not的判断,需要加括号
多组数据连续输入,可使用while try except
字符串存储好处大于列表存储,方便计算
子网掩码的判断:前面为1,后面为0。一旦出现了0,就都是0

描述
示例:
I P 地址  192.168.0.1
子网掩码  255.255.255.0
转化为二进制进行运算:
I P 地址  11000000.10101000.00000000.00000001
子网掩码 11111111.11111111.11111111.00000000
AND运算 11000000.10101000.00000000.00000000
转化为十进制后为:
192.168.0.0
I P 地址  192.168.0.254
子网掩码  255.255.255.0
转化为二进制进行运算:
I P 地址 11000000.10101000.00000000.11111110
子网掩码 11111111.11111111.11111111.00000000
AND运算 11000000.10101000.00000000.00000000
转化为十进制后为:
192.168.0.0
通过以上对两台计算机IP地址与子网掩码的AND运算后,我们可以看到它运算结果是一样的。均为192.168.0.0,所以这二台计算机可视为是同一子网络。
输入一个子网掩码以及两个ip地址,判断这两个ip地址是否是一个子网络。
若IP地址或子网掩码格式非法则输出1,若IP1与IP2属于同一子网络输出0,若IP1与IP2不属于同一子网络输出2。
注:
有效掩码与IP的性质为:1. 掩码与IP每一段在 0 - 255 之间2. 掩码的二进制字符串前缀为网络号,都由‘1’组成;后缀为主机号,都由’0’组成
输入描述:
3行输入,第1行是输入子网掩码、第2,3行是输入两个ip地址
题目的示例中给出了三组数据,但是在实际提交时,你的程序可以只处理一组数据(3行)。
输出描述:
若IP地址或子网掩码格式非法则输出1,若IP1与IP2属于同一子网络输出0,若IP1与IP2不属于同一子网络输出2

def changes(lst):
    s = ""
    for i in lst:
        if i.isdigit():
            if int(i) >= 0 and int(i) <= 255:
                s_bin = bin(int(i))[2:]  # 110
                s += '0' * (8 - len(s_bin)) + s_bin
            else:
                return False
        else:
            return False
    return s
def calculate(sm, IP):
    news = ''
    for i in range(32):
        if sm[i] == "1" and IP[i] == '1':
            news += '1'
        else:
            news += '0'
    return news
def check_sm(sm):
    for i in range(len(sm)):
        if sm[i]=='0':
            if sm[i:]=='0'*(len(sm)-i):
                return True
            else:
                return False
    return False
while 1:
    try:
        a = input().split('.') 
        b = input().split('.')
        c = input().split('.')
        bin_a = changes(a)
        bin_b = changes(b)
        bin_c = changes(c)
        news1 = ""
        news2 = ""
        if not(bin_a and bin_b and bin_c and check_sm(bin_a)) :
            print('1')
        else:
            news1 = calculate(bin_a, bin_b)
            news2 = calculate(bin_a, bin_c)
            if news1 == news2:
                print('0')
            else:
                print('2')
    except:
        break