1. Théorie des nombres
#数论
#%%
#约数个数
# =============================================================================
# count=0
# for i in range(1,10+1):
# if 10%i==0:
# count+=1
# print(count)
# =============================================================================
#合数个数
# =============================================================================
# def is_he(n):
# for i in range(2,n):
# if n%i==0:
# print(n)
# return True#只要找到一个就退出了
# return False
# count=0
# for i in range(1,10+1):
# if is_he(i):
# count+=1
# print(count)
#
# =============================================================================
#质数个数
# =============================================================================
# #可以使用除法删除一点?
# import math
# import time
# def is_zhi(j):
# if j<2:
# return False
# elif j==2:
# return True
# elif j%2==0 or j%3==0 or j%5==0 or j%7==0 :
# return False
#
# else:
# for i in range(2,round(math.sqrt(j))+1):
# if j%i==0:
# return False
# return True
# n=20200506
# count=0
# t1=time.time()
# for i in range(2,n+1+1):
# if is_zhi(i):
# count+=1
# t2=time.time()
# print(count)
# print(t2-t1)
# =============================================================================
#分解质因数
# =============================================================================
# import math
# count=0
# n=2021041820210418
# vetor=[]
# for i in range(1,n+1):
# if n%i==0:
# vetor.append(i)
# for i in range(len(vetor)):
# for j in range(len(vetor)):
# for k in range(len(vetor)):
# if vetor[i]*vetor[j]*vetor[k]==n:
# count+=1
# print(count)
# =============================================================================
#阶乘约数
# =============================================================================
#
#
# """
# 要进行质因数分解
# 随后用到求约数个数的公式:
# (每个质数的次幂+1)相乘
# """
#
#
# # 阶乘约数
#
#
# """
# 100的阶乘,可表示为1x2x3...x100
# 因此可以对参与阶乘的2,3,4,5,6到100进行质因数分解
# 既然质因数分解的数最高也就100
# 那么定义n = 100,也就是要质因数分解的最大的数,就能收集到所需的质数了。
# """
#
# n = 100
# p = [2] # 质数集,其中2
#
#
# for i in range(3, n + 1):
# j = 2
# while j < i:
# if i % j == 0: # 如果有比 i 小的数可以将i整除,就表示i为合数,break结束循环,就不会把i加入质数集中.
# break
# j += 1
# else:
# p.append(i)
#
#
# m = {}
# for i in p:
# m[i] = 1 # 每个质数初始为1,对应公式:”(某一质数的次数 + 1) * (某二质数的次数 + 1)“ 中的1。
#
#
# for i in range(2, n + 1):
# # 遍历 [2, 100] 对应100的阶乘为1x2x3...x100。
# for j in p: # 遍历质数,将每个参与100阶乘中相乘的数都质因数分解一下。# (比如 6 分解成 2*3 ,12 分解成 2*2*3)
# if j > i: # 当所遍历到的质数比要进行质因数分解的数要大时,就直接结束这一层for j in p循环。
# break
# while i % j == 0: # 这里是看 i 可以被 "当前 j" 整除多少次,
# # 当 i 不能再被 "当前 j" 整除时,while循环结束,
# # for j in p循环继续尝试下一个j,直到j > i,满足if条件,break
# i //= j
#
# m[j] += 1 # 让对应的质数个数 + 1
#
# s = 1 # 定义一个变量s,用于接收相乘得出的约数个数。(因为是相乘,所以s要等于1)
#
#
# for i in m.values(): # 所有质因子的个数相乘,就是约数个数了。
# s *= i
# print(s)
#
# =============================================================================
#最小公倍数
# =============================================================================
# def lcm(a,b):
# return a*b//gys(a,b)
#
#
# #最大公约数(好几个数)
# from functools import reduce
# l=[6,9,27,24]
# def gys(a,b):
# if a<b:
# a,b=b,a
# if a%b==0:
# return b
# else:
# return gys(b,a%b)
#
# print(reduce(lcm,l))
# =============================================================================
#elif就是否则的话如果,如果if成立,就不执行;如果if不成立,才会执行。但是if是独立条件,不管第一个执行不执行都无所谓。
#%%
Deux conseils lambda
#lambda
# =============================================================================
# #f=lambda x:x*x
# #print(f(2))
# #lambda的本质就是将一行函数进行简化
# #def get_populuatuion(country):
# # return country[2]
# #-->lambda country:country[2]
# #排序可以用到:
# #countries.sort(key=lambda country:country[2])
# #用到复合函数上
# # def quadratic(a,b,c):
# # return lambda x:a*x*x+b*x+c
# # f=quadratic(-1, 3, 4)
# # print(f(1))
# =============================================================================
3. Structure des données et entrée et sortie
#蓝桥杯学习
#一阶数组
# =============================================================================
# # #读a[]
# # a=list(map(int,input().split()))
# # #a[0]不用
# # b=[0]+[int(i) for i in input().split()]
# # #读n行的数字
# # n=int(input())
# # nums=[]
# # for i in range(n):
# # nums.append(int(input()))
# =============================================================================
#二阶数组
# =============================================================================
# p=[[0]*5 for i in range(2)]
# p.insert()
# p.extend()
#
# =============================================================================
#链表,list并不是真正的链表
# =============================================================================
# #插入
# index=li.index(5)
# li.insert(index,49)
# #删除
# li.pop(index)
# #删除第一个5
# li.remove(5)
# =============================================================================
#队列
# =============================================================================
# #有两个口,一个入口和一个出口,就是普通的排队
# #栈
# #只有唯一的出入口,类似如瓶子里面的东西
# from queue import LifoQueue
# st = LifoQueue()
#
# #用list实现栈
# append送入栈,pop弹出栈顶
# =============================================================================
#二叉树
# =============================================================================
# #平衡二叉树
# #满二叉树
# #每一层的节点数都是满的
# #完全二叉树
# #只在最后一层有缺失,缺失的编号都在最后
# #二叉树的存储
# # tree=['']*n
# # 根节点tree[1]
# # 节点tree[p]的左子节点tree[2*p]
# # 右子节点tree[2*p+1]
# 二叉树的遍历
# 宽度优先遍历
# 深度优先遍历
# :先/中/后序遍历
# 只有中序和(先后)序才能确定一棵树
# =============================================================================
#读取二维矩阵
# =============================================================================
# n,m,k=map(int,input().split())
# a=[[0] for i in range(n)]
# a.insert(0,[0]*(m+1))
# for i in range(1,n+1):
# a[i].extend(map(int,input().split()))
# #insert和extent作用差不多,只是用法有差别。
# =============================================================================
好像说extend是直接加在后面,而append是加一个。
4. Tri
#排序
# =============================================================================
# # sort()是应用在list的方法
# # sorted()可以对所有可迭代的对象进行排序操作
# # sort()是改变原来的列表,而sorted是产生一个新的列表。
# a=[6,4,5,7,3,1]
# b=sorted(a)
# print(b)
# print(b[::-1])
# a.sort(reverse=True)
# sorted(s1,key=lambda s:s[1],reverse=True)
# sorted可以做部分排序,利用切片
# jion可以把一堆东西合在一起
# =============================================================================
#结构体排序
# s.sort(key=lambda x:x[i],reverse=True)
# a=sorted(s,key=lambda x:x[i],reverse=True)
#对一个二维列表的某一列进行排序。
# index=reversed((1,2,0))
# for i in index:
# scores.sort(key=lambda x:x[i],reverse=True)
Cinq, dichotomie
#二分法
# =============================================================================
# # def bin_search(a,n,x):
# # left=0
# # right=n
# # while(left<right):
# # mid=(right+left)//2
# # if(a[mid]>=x):right=mid
# # else:
# # left=mid+1
# # print('[',left,right,']')
# # return left
#
# # n=100
# # a=[i for i in range(1,101)]
# # test=54
# # pos=bin_search(a,n,test)
# # print("test=",a[pos])
# =============================================================================
Six, préfixe et
#前缀和
# =============================================================================
# n=10
# a=[i for i in range(n)]
# print(a)
#
# sum=[0]*n
# for i in range(1,n):
# sum[i]=sum[i-1]+a[i]
# print(sum)
# =============================================================================
Sept, récursivité
#贪心算法
#在每一步都选局部最优
#dfs深度优先搜索(一只老鼠)
#bfs广度优先搜索(好多只老鼠)
#递归
#记忆化
# =============================================================================
# import sys
# sys.setrecursionlimit(300000)#设置递归深度
# def fib(n):
# global cnt
# cnt+=1
# if n==1 or n==2:
# data[n]=1
# return data[n]
# if data[n]!=0:
# return data[n]
# data[n] =fib(n-1)+fib(n-2)
# return data[n]
# data=[0]*3005
# cnt=0
# print(fib(3000))
# print(cnt)
# =============================================================================
8. DFS
#DFS框架
# =============================================================================
# ans #答案,用全局变量表示
# def dfs(层数,其他参数):
# if(出局判断) #到达最底层,或者满足条件退出
# 更新答案 #答案一般用全局变量表示
# return #返回到上一层
# 剪枝 #在进一步dfs之前剪枝
# for(枚举下一层可能的情况):#对每一个情况继续dfs
# if(used[i]==0):
# used[i]=1
# dfs(层数+1,其他参数) #下一层
# used[i]=0 #恢复状态,回溯时,不影响上一层对这个状态的使用
# return #返回到上一层
#
# =============================================================================
# =============================================================================
#
# a=[]
# def mm(n):
# if n>0:
# m=n-1
#
# mm(m)
# a.append(m)
# mm(4)
#
# =============================================================================
# vis=set()
# #集合没有顺序
# def dfs(graph,node):
# if node not in vis:
# vis.add(node)
# print(node)
# for neighbor in graph[node]:
# #print(node+neighbor)
# dfs(graph,neighbor)
#
# graph={'A':set(['B','C']),
# "B":set(['A','D','E']),
# 'C':set(['A','F']),
# 'D':set(['B']),
# 'E':set(['B','F']),
# 'F':set(['C','E'])}
# dfs(graph,'A')
# #一条路走到黑,然后返回来执行另外执行另外一条路。
# =============================================================================
# =============================================================================
#dfs和排列
# from itertools import permutations
# a = 'abc' #对字符串进行permutations排列组合
# for i in permutations(a,3):
# x = ''.join(i)
# print (x,end=' ')
# print ('\n------------------------------------')
#手写全排列
# =============================================================================
# def dfs(s,t):
# if s==t:
# print(a[0:n])
# else:
# for i in range(s,t+1):
# a[s],a[i]=a[i],a[s] #交换
# #print("交换"+str(i))
# dfs(s+1,t) #缩小范围
# a[i],a[s]=a[s],a[i]#恢复
# #print("恢复"+str(i))
# a=[1,2,3,4,5,6,7,8,9]
# n=3
# dfs(0,n-1)
#
# =============================================================================
#手写全排列,从小到大的方式
# =============================================================================
# def dfs(s,t):
# if s==3:
# print(b[0:3])
# else:
# for i in range(t):
# if vis[i]==False:
# vis[i]=True
# b[s]=a[i]
# dfs(s+1,t)
# vis[i]=False
# a=[1,2,3,4,5,6,7,8,9]
# b=[0]*10
# vis=[False]*10
# n=4
# dfs(0,n)
#
# =============================================================================
#组合
# =============================================================================
# vis=[0]*10
# def dfs(k):
# if k==4:
# for i in range(4):
# print(vis[i],end='')
# print()
# else:
# vis[k]=0 #不选第k个
# dfs(k+1) #继续搜下一个
# vis[k]=1 #选k个
# dfs(k+1) #继续搜下一个
# dfs(0)
# #理解成树状图
#
# =============================================================================
# =============================================================================
# def dfs(num):
# global ans
# if num==13:
# if b[10]==b[11]*b[12]:
# ans+=1
# return
# if num==4 and b[1]+b[2]!=b[3]:
# return
# if num==7 and b[4]+b[5]!=b[6]:
# return
# if num==10 and b[7]*b[8]!=b[9]:
# return
# for i in range(1,14):
# if not vis[i]:
# b[num]=i
# vis[i]=1
# dfs(num+1)
# vis[i]=0
#
# ans=0
# b=[0]*15
# vis=[0]*15
# dfs(1)
# print(ans)
# =============================================================================
#方向技巧
# d=[(0,1),(0,-1),(1,0),(-1,0)]
# nx=x+d[i][0]
#树是特殊的图,n个节点,n+1个线。
#树的重心,树上最稳定的地方,
#树的直径,是指树上最远两点的距离,又称为树的最远点对。
#剪枝:把不会产生答案剪掉。
#理解dfs
Neuf, BFS et DFS
#bfs广度优先搜索
# =============================================================================
# graph={
# 'A':['B','C'],
# 'B':['A','C','D'],
# 'C':['A','B','D','E'],
# 'D':['B','C','E','F'],
# 'E':['C','D'],
# 'F':['D'],
# }
#
# def BFS(graph,s):
# #这个是队列,先进先出
# queue = []
# queue.append(s)
# #这个矩阵的看有没有出现过
# seen=set()
# seen.add(s)
# while (len(queue)>0):
# vertex =queue.pop(0)#做一个队列,先进先出
# nodes=graph[vertex]
# for w in nodes:
# if w not in seen:
# queue.append(w)
# seen.add(w)
# print(vertex)
# BFS(graph,'A')
#
# =============================================================================
#dfd深度有线搜索
# =============================================================================
# graph={
# 'A':['B','C'],
# 'B':['A','C','D'],
# 'C':['A','B','D','E'],
# 'D':['B','C','E','F'],
# 'E':['C','D'],
# 'F':['D'],
# }
#
# def DFS(graph,s):
# #这个是队列,先进先出
# stack = []
# stack.append(s)
# #这个矩阵的看有没有出现过
# seen=set()
# seen.add(s)
# while (len(stack)>0):
# vertex =stack.pop()#做一个栈,先进后出。pop没有索引,就删除最后一个。
# nodes=graph[vertex]
# for w in nodes:
# if w not in seen:
# stack.append(w)
# seen.add(w)
# print(vertex)
# DFS(graph,'A')
# =============================================================================
#最短路径
# =============================================================================
# graph={
# 'A':['B','C'],
# 'B':['A','C','D'],
# 'C':['A','B','D','E'],
# 'D':['B','C','E','F'],
# 'E':['C','D'],
# 'F':['D'],
# }
#
# def BFS(graph,s):
# #这个是队列,先进先出
# queue = []
# queue.append(s)
# #这个矩阵的看有没有出现过
# seen=set()
# seen.add(s)
# parent={s:None}
# while (len(queue)>0):
# vertex =queue.pop(0)#做一个队列,先进先出
# nodes=graph[vertex]
# for w in nodes:
# if w not in seen:
# queue.append(w)
# seen.add(w)
# parent[w]=vertex
#找父节点
# print(vertex)
# return parent
# parent=BFS(graph,'A')
#
# v='E'
# while v!=None:
# print(v)
# v=parent[v]
# =============================================================================
#优先队列
# import heapq#引入
# pqueue=[]
# heapq.heappush(pqueue, (1,'A'))#添加元组
# heapq.heappush(pqueue, (7,'E'))
# heapq.heappush(pqueue, (3,'B'))
# heapq.heappop(pqueue)#删除元组
# =============================================================================
# #dijkstra算法
# import heapq
# import math
# graph={
# 'A':{'B':5,'C':1},
# 'B':{'A':5,'C':2,'D':1},
# 'C':{'A':1,'B':2,'D':4,'E':8},
# 'D':{'B':1,'C':4,'E':3,'F':6},
# 'E':{'C':8,'D':3},
# 'F':{'D':6},
# }
# def init_distance(graph,s):
# distance={s:0}
# for vertex in graph:
# if vertex!=s:
# distance[vertex]=math.inf
# return distance
# def dijkstra(graph,s):
# #这个是队列,先进先出
# pqueue = []
# heapq.heappush(pqueue, (0,s))
# #这个矩阵的看有没有出现过
# seen=set()
#
# parent={s:None}
# distance=init_distance(graph,s)
#
# while (len(pqueue)>0):
# pair=heapq.heappop(pqueue)
# dist=pair[0]
# vertex=pair[1]
# seen.add(vertex)
# nodes=graph[vertex].keys()
# for w in nodes:
# if w not in seen:
# if dist+graph[vertex][w]<distance[w]:
# heapq.heappush(pqueue, (dist+graph[vertex][w],w))
# parent[w]=vertex
# distance[w]=dist+graph[vertex][w]
# return parent,distance
#
# parent,distance=dijkstra(graph,'A')
# print(parent)
# print(distance)
#
# # a=[1,2,3] a[::-1]代表倒序
# =============================================================================
#并查集
#动态规划(选或者不选)
Dix, programmation dynamique
#动态规划
# =============================================================================
# def solve(s):
# Min=[int(1e12)]*(s+1) #初始化为无穷大,防止被溢出
# Min[0]=0
# for j in range(cnt):
# for i in range(type[j],s+1):
# Min[i]=min(Min[i],Min[i-type[j]]+1)
# print(Min[s])
# #先算只有1块钱,从1-s有多少个,然后逐步更新。
#
# cnt=5
# type=[1,5,10,25,50]
# s=int(input())
# solve(s)
#
# =============================================================================
#0-1背包问题
# =============================================================================
# def solve(n,C):
# for i in range(1,n+1):
# for j in range(0,C+1):
# if c[i]>j: dp[i][j]=dp[i-1][j]
# else: dp[i][j]=max(dp[i-1][j],dp[i-1][j-c[i]]+w[i])
# return dp[n][C]
#
# N=3011
# dp=[[0]*N for j in range(N)]
# w=[0]*N
# c=[0]*N
# n,C=map(int,input().split())
# for i in range(1,n+1):
# c[i],w[i]=map(int,input().split())
# print(solve(n,C))
#
# =============================================================================
#算2020
# =============================================================================
# dp=[[[0]*2222 for _ in range(11)]for j in range(2222)]
# for i in range(0,2023):
# dp[i][0][0]=1
# for i in range(1,2023):
# for j in range(1,11):
# for k in range(1,2023):
# if k<i:
# dp[i][j][k]=dp[i-1][j][k]
# else:
# dp[i][j][k]=dp[i-1][j][k]+dp[i-1][j-1][k-i]
# print(dp[2000][10][2000])
# =============================================================================
#普通背包问题
#线性dp
# =============================================================================
# m,n=map(int,input().split())
# a=[0]+list(map(int,input().split()))
# b=[0]+list(map(int,input().split()))
# dp=[[0]*(n+1) for i in range(m+1)]
# for i in range(1,m+1):
# for j in range(1,n+1):
# if a[i]==b[j]:
# dp[i][j]=dp[i-1][j-1]+1
# else:
# dp[i][j]=max(dp[i-1][j],dp[i][j-1])
# print(dp[m][n])
#
#
# =============================================================================
#称重
# =============================================================================
# n=int(input())
# a=list(map(int,input().split()))
# ans=set()
# ans.add(a[0])
# for i in a[1:]:
# for j in ans.copy():
#对集合添加元素,必须复制一个copy
# ans.add(i)
# ans.add(j+i)
# if j-i!=0:
# ans.add(abs(j-i))
# print(len(ans))
#
# =============================================================================
#状态压缩dp
#树形dp
# =============================================================================
# #字符串的操作
# #合并字符串
# #''.join([str1,str2])
# #插入
# # str_list=list(str1)
# # str_list.insert(index,'aaa')
# # aa=''.join(str_list)
# #重复输出
# # str*2
# #print('\n')
# #str3 in str1
# #str2,str3=str3,str2
# #在范围内查找
# #str1='12345678abcdefghi'
# #print(str1.find('456',2,20))#输出3
# #ord->字符变成数字
# #chr->数字转化成字符
# #将空格消除和换行去掉
# #s.replace(' '.'').replace('\n','')
# =============================================================================
#自己写动态规划
# =============================================================================
# arr=[1,2,4,1,7,8,9,0,7,5,3,14,5]
#
# def dpp(arr):
# dp=[0 for i in range(len(arr))]
# for i in range(len(arr)):
# if i==0:
# dp[i]=arr[i]
# elif i==1:
# dp[i]=max(arr[0],arr[i])
# else:
# A=arr[i]+dp[i-2]
# B=dp[i-1]
# dp[i]=max(A,B)
# return dp[len(arr)-1]
# #递归
# def dg(m):
# if m==0:
# return arr[0]
# elif m==1:
# return max(arr[0],arr[1])
# else:
# A=arr[m]+dg(m-2)
# B=dg(m-1)
# return max(A,B)
#
# print(dg(5))
# =============================================================================
Onze, correspondance KMP
#kmp匹配算法
# =============================================================================
# #匹配字符串
# def build_next(patt):
# '''
# 计算Next数组
#
# Parameters
# ----------
# patt : TYPE
# DESCRIPTION.
#
# Returns
# -------
# None.
#
# '''
# next=[0]
# prefix_len=0#当前共同前后缀的长度
# i=1
# while i<len(patt):
# if patt[prefix_len]==patt[i]:
# prefix_len+=1
# next.append(prefix_len)
# i+=1
# else:
# if prefix_len==0:
# next.append(0)
# i+=1
# #当第一个没有前缀和,就一直为0
# else:
# prefix_len = next[prefix_len-1]
# #突然一个匹配不上了,prefix就减去一个看看能不能匹配上。不行就继续减。
# return next
#
#
#
# def kmp_search(string,patt):
# next=build_next(patt)
#
# i=0 #主串中的指针
# j=0 #字串里的指针
# m=[]
# while i < len(string):
# if string[i] == patt[j]: #字符匹配,指针后移
# i+=1
# j+=1
# elif j>0:
# j=next[j-1]#字符失配,根据next跳过字串前面的一些字符(前面j个不与i进行比较。)
# else:
# i+=1#字串第一个字符就失配
#
# if j==len(patt):
# #匹配成功
# m.append(i-j)
# j=0
# return m
#
# string='abbbabbabsisnahhahha'
# patt='ab'
# n=kmp_search(string,patt)
# def tran(strr):
# p=[]
# for i in strr:
# i=chr(ord(i)-32)
# p.append(i)
# Strr=''.join(p)
# return Strr
# String=string.replace(patt,tran(patt))#不能在原来的字符串上修改。
# print('位置:',n)
# print(String)
# =============================================================================
12. Décorateur
#质数的生成
# =============================================================================
# import time
# #装饰器
# def display_time(func):
# def wrapper():
# t1=time.time()
# result=func()
# t2=time.time()
# print(t2-t1)
# return result
# return wrapper
#
# def is_prime(num):
# if num<2:
# return False
# elif num==2:
# return True
# else:
# for i in range(2,num):
# if num%i==0:
# return False
# return True
#
# @display_time#装饰器
# def prime_nums():
# count=0
# for i in range(2,100):
# if is_prime(i):
# count+=1
# return count
#
# count=prime_nums()
# print(count)
# =============================================================================
Treize, les bases du python
divmod(x,y) 商余,(x//y,x%y),同样输出商和余数divmod(10,3)结果为(3,1)
ord(x)x为字符
chr(u)
str.count(sub)返回字串Sub在str中出现的次数。
str.lower()
str.upper()转化大小写