# 海陸雙拼筆記🐳🐒
## :memo: SCL 模板
#### BST 二元搜尋樹
:::spoiler
```python=1
class tree():
def __init__(self):
self.data=0
self.right=None
self.left=None
def create_tree(root,val):
newnode=tree()
newnode.data=val
newnode.left=None
newnode.right=None
if root==None:
root=newnode
return root
else:
current=root
while current!=None:
backup=current
if current.data>val:
current=current.left
else:
current=current.right
if backup.data>val:
#adj[backup.data][val]=1
#adj[val][backup.data]=1
backup.left=newnode
else:
#adj[backup.data][val]=1
#adj[val][backup.data]=1
backup.right=newnode
return root
data=[5,454,456,1,5,6,46,46,649,1564,156,1464,1454,14,566]
#adj=[[0]*101 for i in range(101)]
ptr=None
for i in range(len(data)):
ptr=create_tree(ptr,data[i])
def inorder(ptr):
if ptr!=None:
inorder(ptr.left)
print(ptr.data,end=" ")
inorder(ptr.right)
inorder(ptr)
```
:::
#### heap 堆積樹
:::spoiler
```python=1
num=[454,456478,4564,564,54,564,56,4,5678,79,455456,4,45,456,4,14,565,467,5325]
num_size=len(num)
def heapify(n,i):
root=i
l=i*2
r=i*2+1
if l<n and num[l]<num[root]:
root=l
if r<n and num[r]<num[root]:
root=r
if i!=root:
num[root],num[i]=num[i],num[root]
heapify(n,root)
def heapsort():
for i in range(num_size//2,-1,-1):
heapify(num_size,i)
for i in range(num_size-1,-1,-1):
heapify(i,0)
num[i],num[0]=num[0],num[i]
heapsort()
for i in num:
print(i,end=" ")
```
:::
#### kruskal 最小生成樹
:::spoiler
```python=1
import heapq
pq=[]
num=[1]*101
parent=[0]*101
def findparent(a):
while a!=parent[a]:
a=parent[a]
return a
n,m=map(int,input().split())
for i in range(m):
a,b,w=map(int,input().split())
heapq.heappush(pq,(w,a,b))
for i in range(101):
parent[i]=i
i=numEdge=result=0
while i<m and numEdge<n:
edge=heapq.heappop(pq)
a=findparent(edge[1])
b=findparent(edge[2])
if a!=b:
if num[a]>num[b]:
num[a]+=num[b]
parent[b]=a
else:
num[b]+=num[a]
parent[a]=b
result+=edge[0]
numEdge+=1
i+=1
if numEdge==n-1:
print(result)
else:
print("no")
```
:::
#### 最小生成樹陣列版
:::spoiler
```python=1
n,m=map(int,input().split())
count=[]
alldot=[]
somedot=[]
for i in range(m):
a,b,c=map(str,input().split())
x=[]
x.append(a)
x.append(b)
if a not in somedot:
somedot.append(a)
if b not in somedot:
somedot.append(b)
count.append(int(c))
alldot.append(x)
num=[i for i in range(len(somedot))]
s=sorted(count)
sum=0
for i in range(len(s)):
change=count.index(int(s[i]))
if num[somedot.index(alldot[change][0])] != num[somedot.index(alldot[change][1])]:
sum+=s[i]
yo=num[somedot.index(alldot[change][0])]
for v in range(len(num)):
if num[v]==yo:
num[v]=num[somedot.index(alldot[change][1])]
count[change]=(n+1)
print(sum)
```
:::
#### huffman 霍夫曼樹陣列版
:::spoiler
```python=1
#yesso是已經排序
#noso是未排序
n=eval(input())
for i in range(n):
numnoso=[]
m=list(map(int,input().split(',')))
dot=[chr(65+i) for i in range(len(m))]
alldot=[chr(65+i) for i in range(len(m))]
final=['' for i in range(len(m))]
for x in range(len(m)):
numnoso.append(m[x])
numyesso=sorted(numnoso)
for j in range(len(m)-1):
x=numyesso[0]
y=numyesso[1]
z=x+y
if x==y:
firste=dot[numnoso.index(x)]
k=0
while 1 :
if numnoso[numnoso.index(y)+k]==numnoso[numnoso.index(x)] and dot[numnoso.index(y)+k]!=firste:
seconde=dot[numnoso.index(y)+k]
break
k+=1
else:
firste=dot[numnoso.index(x)]
seconde=dot[numnoso.index(y)]
for j in range(len(final)):
if numnoso[j]==x and dot[j]==firste:
final[j]+='0'
for j in range(len(final)):
if numnoso[j]==y and dot[j]==seconde:
final[j]+='1'
for i in range(len(dot)):
if dot[i]==firste:
dot[i]=firste+seconde
elif dot[i]==seconde:
dot[i]=firste+seconde
for j in range(len(numnoso)):
if numnoso[j]==x or numnoso[j]==y:
numnoso[j]=z
numyesso.pop(0)
numyesso.pop(0)
numyesso.append(z)
numyesso.sort()
for j in range(len(alldot)):
final[j]=len(final[j])
print(*final,sep=',')
```
:::
#### huffman 霍夫曼樹
:::spoiler
```python=1
import heapq
pq=[]
hf=[0]*101
code=[0]*101
def dfs(id,leval):
if hf[id].t==False:
code[leval]="0"
dfs(hf[id].le,leval+1)
code[leval]="1"
dfs(hf[id].ri,leval+1)
else:
print(hf[id].ch,end=" ")
for i in range(leval):
print(code[i],end=" ")
print()
class node:
def __init__(self,id,ch,w,t,le,ri):
self.id=id
self.ch=ch
self.w=w
self.t=t
self.le=le
self.ri=ri
c=["a","b",'c',"d","e"]
w=[10,13,78,4,5]
num=len(c)
tmp=[]
for i in range(len(c)):
hf[i]=node(i,c[i],w[i],True,0,0)
tmp.append(hf[i])
tmp=sorted(tmp,key=lambda x:x.w)
while len(tmp)>1:
a=tmp[0]
del tmp[0]
b=tmp[0]
del tmp[0]
n=node(num,None,a.w+b.w,False,a.id,b.id)
hf[num]=n
tmp.append(hf[num])
tmp=sorted(tmp,key=lambda x:x.w)
num+=1
dfs(tmp[0].id,0)
# s=("abs")
# t=s.reversed(s)
# print(t)
```
:::
#### DFS 迷宮
:::spoiler
```python=1
class point:
def __init__(self,r,c,dis):
self.r=r
self.c=c
self.dis=dis
def bound(row,col,nr,nc):
if row>0 and row<=nr and col>0 and col<=nc:
return 1
else:
return 0
map1=[[0]*101 for i in range(101)]
val=[[0]*101 for i in range(101)]
gor=[0,1,0,-1]
goc=[1,0,-1,0]
myq=[]
r,c=map(int,input().split())
for i in range(1,r+1):
line=input().split()
for j in range(c):
map1[i][j+1]=int(line[j])
sr,sc=map(int,input().split())
myp=point(sr,sc,1)
val[myp.r][myp.c]=1
myq.append(myp)
while len(myq)>0:
nextp=myq[0]
del myq[0]
for i in range(4):
if bound(nextp.r+gor[i],nextp.c+goc[i],r,c) and map1[nextp.r+gor[i]][nextp.c+goc[i]]==1 and val[nextp.r+gor[i]][nextp.c+goc[i]]==0:
val[nextp.r+gor[i]][nextp.c+goc[i]]=nextp.dis+1
tmp=point(0,0,0)
tmp.r=nextp.r+gor[i]
tmp.c=nextp.c+goc[i]
tmp.dis=nextp.dis+1
myq.append(tmp)
for i in range(r):
for j in range(c):
print(val[i+1][j+1],end=" ")
print()
```
:::
#### Dijkstra
:::spoiler
```python=1
from heapq import *
city={}
G={}
pq=[]
dis=[10000000]*101
v=[0]*101
def getcityindex(p):
if p not in city.keys():
city[p]=len(city)
return city[p]
class Edge:
def __init__(self,s,t,w):
self.s=s
self.t=t
self.w=w
n=int(input())
for i in range(n):
a,b,w=input().split()
a=getcityindex(a)
b=getcityindex(b)
e1=Edge(a,b,w)
e2=Edge(b,a,w)
if a in G.keys():
G[a].append(e1)
else:
G[a]=[e1]
if b in G.keys():
G[b].append(e2)
else:
G[b]=[e2]
s=getcityindex(input())
p=(0,s)
heappush(pq,p)
dis[s]=0
while len(pq)>0:
p=heappop(pq)
s=p[1]
if v[s]==0:
for edge in G[s]:
if v[edge.t]==0:
if dis[edge.t]>dis[s]+edge.w:
dis[edge.t]=dis[s]+edge.w
p=(dis[edge.t],edge.t)
heappush(pq,p)
for i in range(len(city)):
print(dis[i],end=" ")
```
:::
#### Dijkstra陣列版
:::spoiler
```python=1
n=eval(input())
dot=[]
tree=[[0 for i in range(10)]for i in range(10)]
for i in range(n):
a,b,c=map(str,input().split())
if a not in dot :
dot.append(a)
if b not in dot:
dot.append(b)
tree[dot.index(a)][dot.index(b)]=int(c)
tree[dot.index(b)][dot.index(a)]=int(c)
door=[0 for i in range(len(dot))]
ans=[99999 for i in range(len(dot))]
m=input()
ans[dot.index(m)]=0
door[dot.index(m)]=1
while 1:
if door.count(1)==len(door):
break
else:
for j in range(len(dot)):
if tree[dot.index(m)][j]!=0 and (ans[dot.index(m)]+tree[dot.index(m)][j])<ans[j]:
ans[j]=tree[dot.index(m)][j]+ans[dot.index(m)]
little=99999
for k in range(len(ans)):
if ans[k]<little and door[k]!=1:
little=ans[k]
for j in range(len(ans)):
if ans[j]==little and door[j]!=1:
door[j]=1
m=dot[j]
break
print(*ans)
```
變化題:沒給距離的最短路徑
```python=1
#UVA216
def dist(p,q,m,n):
return ((p-m)**2+(m-n)**2)**0.5
def dfs(depth,path):
if depth==n:
if path<min_dis:
min_dis=path
for i in range(n):
rx[i]=tmpx[i]
ry[i]=tmpx[u]
return
for i in range(n):
id used[i]==0:
used[i]=1
tmpx[depth]=x[i]
tmpx[depth]=y[i]
if depth==0:
dfs(depth+1,0)
else:
dfs(depth+1,path+dist(tmpx[depth],tmpy[depth],tmpx[depth-1],tmpy[depth-1]))
uesd[i]=1
n=int(input())
min_dis=10000
x=[]
y=[]
uesd=[0]*n
tmpx=[0]*n
tmpy=[0]*n
rx=[0]*n
ry=[0]*n
for i in range(n):
s,k=map(int,input().split())
x.append(s)
y.append(k)
dfs(0,0)
print(min_dis) #距離
for i in range(1,n):
print(rx[i-1],ry[i-1],rx[i],ry[i],dist(rx[i-1],ry[i-1],rx[i],ry[i]))
```
:::
#### dijkstramap
:::spoiler
```python=1
import heapq
import sys
ntime=int(input())
inf=(1000000)
direct=(0,1,0,-1,0)
for i in range(ntime):
m=int(sys.stdin.readline().strip())
n=int(sys.stdin.readline().strip())
matrix=[]
m_1=range(m+1)
n_1=range(n+1)
for j in m_1[0:-1]:
matrix.append(list(map(int,sys.stdin.readline().strip().split())))
values=[[inf for a in n_1] for b in m_1]
value[0][0]=matrix[0][0]
pq=[]
heapq.heappush(pq,(values[0][0],0,0))
while pq:
value,x,y=heapq.heappop(pq)
for c in range(4):
nx,ny=direct[c]+x,direct[c+1]+y
if nx<0 or ny<0 or nx>=n and ny>=m:
contiune
val=value+matrix[ny][nx]
if values[ny][nx]>val:
values[ny][nx]=val
heapq.heappush(pq,[val,nx,ny])
sy.stdout.write(f'{values[m-1][n-1]}\n')
```
:::
#### distance
:::spoiler
```python=1
m=int(input())
node=[[0]*9 for i in range(9)]
distance=[0]*9
for i in range(m):
a,b=map(int,input().split())
node[a][b]=1
node[b][a]=1
def dfs(x,px):
for i in range(9):
if node[x][i]==1 and i!=px:
distance[i]=distance[x]+1
dfs(i,x)
def tree_distance(x,y):
distance[x]=0
dfs(x,y)
print(distance[y])
sr,sc=map(int,input().split())
tree_distance(sr,sc)
```
:::
#### diameter
:::spoiler
```python=1
m=int(input())
adj=[[0]*7 for i in range(7)]
for i in range(m):
a,b=map(int,input().split())
adj[a][b]=1
adj[b][a]=1
diamter=0
def dfs(x,px):
global diamter
h1=0
h2=0
for y in range(7):
if adj[x][y]==1 and y!=px:
h=dfs(y,x)+1
if h>h1:
h2=h1
h1=h
elif h>h2:
h2=h
diamter=max(diamter,h1+h2)
return h1
def tree_diamter():
global diamter
diamter=0
root=0
dfs(root,root)
print(diamter)
tree_diamter()
#h032
while 1:
try:
n=int(input())
except:
break
deg=[0]*n
parent=[-1]*n
height=[0]*n
for i in range(n-1):
s,t=map(int,input().split())
parent[t]=s
deg[s]+=1
que=[v for v in range(n) if deg[v]==0]
front=0
diamter=0
while front<len(que):
v=que[front]
front+=1
p=parent[v]
if p<0:
break
diamter=max(diamter,height[p]+height[v]+1)
height[p]=max(height[p],height[v]+1)
deg[p]-=1
if deg[p]==0:
que.append(p)
print(diamter)
```
:::
#### 前中轉後序 tree
:::spoiler
```python=1
n=int(input())
prefix=[]
infix=[]
def travesal(n,ls,rs):
global prefix,infix
postfix=[]
if ls==rs:
return [prefix[n]]
if ls>rs:
return []
pos=infix.index(prefix[n])
N=[prefix[n]]
L=travesal(n+1,ls,pos-1)
R=travesal(n+(pos-ls)+1,pos+1,rs)
if R==None:
R=[]
if L==None:
L=[]
for a in L:
postfix.append(a)
for a in R:
postfix.append(a)
for a in N:
postfix.append(a)
return postfix
for i in range(n):
infix=input().split(",")
prefix=input().split(",")
y=travesal(0,0,len(prefix)-1)
for a in y:
print(a,end=' ')
```
:::
#### 後中轉前序 tree
:::spoiler
```python=1
prefix=[]
infix=[]
def travesal(n,ls,rs):
global prefix,infix
postfix=[]
if ls==rs:
return [prefix[n]]
if ls>rs:
return []
pos=infix.index(prefix[n])
N=[prefix[n]]
R=travesal(n-1,pos+1,rs)
L=travesal(n-(rs-pos)-1,ls,pos-1)
if R==None:
R=[]
if L==None:
L=[]
for a in N:
postfix.append(a)
for a in L:
postfix.append(a)
for a in R:
postfix.append(a)
return postfix
infix=input().split()
prefix=input().split()
y=travesal(len(prefix)-1,0,len(prefix)-1)
for a in y:
print(a,end="")
```
:::
#### 中轉後序 算術
:::spoiler
```python=1
list1=[]
list2=[]
list3=[]
list1=input()
for i in list1:
if i.isdigit():
list2.append(i)
elif i=="(":
list3.append("(")
elif i=="+" or i=="-":
if len(list3)>0:
while list3[-1]=="+" or list3[-1]=="-" or list3[-1]=="*" or list3[-1]=="/":
list2.append(list3.pop(-1))
list3.append("+")
elif i=="*" or i=="/":
if len(list3)>0:
while list3[-1]=="*" or list3[-1]=="/":
list2.append(list3.pop(-1))
list3.append("*")
elif i==")":
if len(list3)>0:
while list3[-1]!="(":
list2.append(list3.pop(-1))
list3.pop(-1)
for i in list3:
list2.append(i)
print("".join(list2))
```
:::
#### 後中轉前序 算術
#### pathsum
:::spoiler
```python=1
def run(n,n1,sum,p):
global tree
if n==n1:
print(sum)
else:
s=0
if n%2==0:s=int(n/2)
else:s=int((n-1)/2)
if not n==1 and p!=s:
run(s,n1,sum+int(tree[s]),n)
s=int(n*2)
if tree[s]!='null' and p!=s:
run(s,n1,sum+int(tree[s]),n)
s=int(n*2+1)
if tree[s]!="null" and p!=s:
run(s,n1,sum+int(tree[s]),n)
tree=["null",1,2,3,4,5,"null",7,"null",'null',"null","null",'null',"null","null",'null',"null"]
x1,x2=4,7
run(x1,x2,x1,-1)
```
:::
#### DP knapsack
:::spoiler
```python=1
#無限背包
m=20
w=100
cost=[int(i) for i in input().split()]
weight=[int(i) for i in input().split()]
c=[0]*(w+1)
def knapsack(n,w):
for i in range(n):
for j in range(weight[i],w+1):
c[j]=max(c[j],c[j-weight[i]]+cost[i])
print(c[w])
#有限背包
n=20
w=100
c=[0]*(w+1)
cost=[int(i) for i in input().split()]
weight=[int(i) for i in input().split()]
number=[int(i) for i in input().split()]
def knapsack(n,w):
for i in range(n):
num=min(number[i],w//weight[i])
k=1
while num>0:
if k>num:
k=num
num-=k
j=w
while j>=weight[i]*k:
c[j]=max(c[j],c[j-weight[i]*k]+cost[i]*k)
j-=1
k*=2
#湊硬幣
price=[5,2,6,11,1]
c=[False]*1000
def knapsack(m):
c[0]=True
for i in range(5):
for j in range(price[i],m+1):
c[j]|=c[j-price[i]]
if c[m]:
print("y")
else:
print("n")
#湊最少
price=[5,2,6,11,17]
c=[10000]*1
def change(m):
c[0]=0
for i in range(5):
for j in range(price[i],m+1):
c[j]=min(c[j],c[j-price[i]+1])
print("最少需要%d個硬幣"%(c[m]))
#幾種湊法
coins=[1,2,5,10,20,50,100]
def coin_sum(total,coins):
way=[1]+([0]*tatal)
for coin in coins:
for i in range(coin,total+1):
way[i]=way[i-coin]
return [total]
#P錢幣
can=[False]*1001
num=int(input())
data=[int(i) for i in input().split()]
max_v=sum(data)
can[0]=True
for i in range(num):
for k in range(max_v,data[i]-1,-1):
can[k]|=can[k-data[i]]
ans=[]
for i in range(1,max_v):
if can[i]:
ans.append(i)
print(len(ans))
for i in ans:
print(i,end=" ")
```
:::
#### 關節點
:::spoiler
109模擬試題 G
方法一
尋找一張圖的關節點有幾個點:利用 DFS 從第一個開始當作 root 開始建樹,只要發現連結
的點尚未走過就當作自己的 child,而如果是有走過的點而且不是自己的 parent 表示有一條
back edge,利用這些自己這個點的 back edge 和所有自己的 **children 能走到最遠的的祖先去
紀錄整體能走到最遠的的祖先到哪裡,則那位祖先只要不是 root 就是其中一個關節點**(因為
它的 children 只要不經過這個點就無法連過去它 parent 以上的祖先)。而判斷祖先是否為關
節點僅要判斷其 children 是否有兩個以上即可。
整理:
(1)若點p是深度優先搜尋樹的根節點,因為深度優先搜尋樹的子樹之間不會相連,會相連就會屬於同一子樹,所以點p只要有兩個以上的子樹,則點p就是關節點(articulation point)。
(2)若點p不是深度優先搜尋樹的根節點,點p的每個子孫都有back edge可以連到點p的祖先(不含點p),該點就不是關節點(articulation point),若有一個子孫沒有back edge,該點就是關節點(articulation point)。
```python=1
#方法一
paths=[]
Articulation=[] #關節點
tree_leval=0
v=[]
up=[]
def dfs(p,t):
global paths,Articulation,tree_leval,v,up
tree_leval+=1
v[t]=tree_leval
up[t]=tree_leval
child=0 #P點有幾個兒子
Ap=False
nexp_point=0
for i in range(0,len(paths[t])):
nexp_point=paths[t][i]
if nexp_point!=p:
if v[nexp_point]>0:
up[t]=min(up[t],v[nexp_point])
else:
child+=1
dfs(t,nexp_point)
up[t]=min(up[t],up[nexp_point])
if up[nexp_point]>=v[t]:
AP=True
if (t==p and child>1) or (t!=p and AP==True):
Articulation.append(t)
while 1:
n=int(input())
if n==0:
break
root=0
paths=[[] for i in range(n+1)]
v=[0 for i in range(n+1)]
up=[0 for i in range(n+1)]
Articulation=[]
while 1:
x=[int(i) for i in input().split()]
if root==0:
root=x[0]
if x[0]==0:
break
for i in range(1,len(x)):
if x[i] not in paths[x[0]]:
paths[x[0]].append(x[i])
if x[0] not in paths[x[i]]:
paths[x[i]].append(x[0])
dfs(root,root)
print(len(Articulation))
v=[0 for i in range(0,n+1)]
```
方法二 走訪
關節點指的是在一個連通圖(DFS 或 BFS 可以走到所有點)中,如果移除該點,會使得該圖不再是連通圖,則該點為關節點。
結論:只要有一點不能連到其他全部的點,此點則為關節點,**此法比較容易理解,但效率不好**
```python=1
import copy
while 1:
n=int(input())
if n==0:
break
paths=[[0 for i in range(n+1)] for j in range(n+1)]
AP=[] #紀錄誰是關節點
while 1: #讀入paths
x=[int(i) for i in input().split()]
if x[0]==0:
break
for i in range(1,len(x)):
paths[x[0]][x[i]]=1
paths[x[i]][x[0]]=1
cnt=0
visited1=[0 for i in range(n+1)]
for i in range(1,n+1):
visited=visited1.copy()
bfs=[]
pos=i%n+1 #下一點為起點,如果最後一點就第一點
bfs.append(pos)
while len(bfs):
pos=bfs[0]
bfs.pop(0) #移除第一點
vistied[pos]=1
for j in range(1,n+1):
if j==i: #拿掉的跳過不做
continue
if visited[j]==0 and paths[pos][j]==1:
bfs.append(j)
for j in range(1,n+1):
if visited[j]==0 and i!=j:
cnt+=1
AP.append(i)
break
print(cnt)
print("關節點",AP)
```
:::
#### loop
:::spoiler
```python=1
import copy
paths1=[[] for i in range(21)]
vertex1=[0 for i in range(21)]
visited=[]
paths=[]
loop_list=[]
loop=-1
def dfs(v):
global paths,visited,loop_list,loop
count=0
if visited[v]==1:
loop=v
return -1
visited[v]=1
count=1
for i in paths[v]:
paths[i].remove[v]
y=dfs(i)
if y==-1 and loop!=-1:
loop_list.append(v)
if v==loop:
loop=-1
return -1
count+=y
return count
n=int(input())
for i in range(n):
paths=copy.copy(paths1)
vertex=copy.copy(vertex1)
visited=copy.copy(vertex1)
instr=input()
vertex_list=[]
for a in instr:
x=[int(i) for i in a.split(",")]
paths[x[0]].append(x[1])
paths[x[1]].append(x[0])
if vertex[x[0]]==0:
vertex_list.append(x[0])
if vertex[x[1]]==0:
vertex_list.append(x[1])
vertex[x[0]]=1
vertex[x[1]]=1
vertex_list=sorted(vertex_list)
for a in range(0,vertex_list[-1]):
paths[a]=sorted(paths[a])
loop_list=[]
count=0
count=dfs(vertex_list[0])
if len(loop_list)>0:
loop_list=sorted(loop_list)
for a in loop_list:
print(a,end=" ")
else:
if count==len(vertex_list):
print("T")
else:
print('F')
```
:::
#### 經典LCS 2、3
:::spoiler
```python=1
def lcs(s1,s2):
n1=len(s1)
n2=len(s2)
dp=[[None]*(n2+1) for _ in range(n1+1)]
for i in range(n1+1):
for j in range(n2+1):
if i==0 or j==0:
dp[i][j]=0
elif s1[i-1]==s2[j-1]:
dp[i][j]=dp[i-1][j-1]+1
else:
dp[i][j]=max(dp[i-1][j],dp[i][j-1])
return dp[n1][n2]
x,y=map(str,input().split())
print(lcs(x,y))
```
```python=1
def lcs(s1,s2,s3):
n1=len(s1)
n2=len(s2)
n3=len(s3)
dp=[[[None]*(n2+1) for _ in range(n1+1)] for _ in range(n3+1)]
for k in range(n3+1):
for i in range(n1+1):
for j in range(n2+1):
if i==0 or j==0 or k==0:
dp[k][i][j]=0
elif s1[i-1]==s2[j-1]==s3[k-1]:
dp[k][i][j]=dp[k-1][i-1][j-1]+1
else:
dp[k][i][j]=max(dp[k][i-1][j],dp[k][i][j-1],dp[k-1][i][j])
return dp[n3][n1][n2]
x=list(input())
y=list(input())
z=list(input())
print(lcs(x,y,z))
```
:::
#### LCS LIS
:::spoiler
```python=1
#a676
n=int(input())
target=None
while 1:
try:
line=[int(i) for i in input().split()]
line.insert(0,0)
ans=line[:]
for i,l in enumerate(line):
ans[l]=i
if target==None:
target=ans[:]
continue
## LCS
dp=[[0]*(n+1) for i in range(n+1)]
for i in range(1,n+1):
for j in range(1,n+1):
if target[i]==ans[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[n][n])
except:
break
```
```python=1
#d052
for _ in range(int(input())):
n=int(input())
if n==0:
print(0)
contiune
a=[None]*n
for i in range(n):
a[i]=int(input())
LIS=[None]*n
LDS=[None]*n
ans=0
for i in range(n-1,-1,-1):
LIS[i]=1
LDS[i]=1
for j in range(n-1,i,-1):
if a[i]>a[j] and LIS[i]<=LIS[j]:
LIS[i]=LIS[j]+1
if a[i]<a[j] and LDS[i]<=LDS[j]:
LDS[i]=LDS[j]+1
if ans<LIS[i]+LDS[i]-1:
ans=lIS[i]+LDS[i]-1
print(ans)
```
:::
#### 產生子序列
:::spoiler
```python=1
arr=[int(i) for i in input().split()]
finish=[]
size=len(arr)
end=2**size
for index in range(end):
array=[]
for j in range(size):
if (index>>j)%2:
array.append(arr[j])
finish.append(array)
print(finish)
```
:::
#### 01背包問題(取或不取)
:::spoiler
```python=1
def f(w,v): #重量weight, 價值value
for i in range(1, l+1): #l=len(w)-1
for j in range(1, m+1): #m=背包容量
if j>=w[i]: #如果當前的容量裝得下物品
dp[i][j]=max(dp[i-1][j-w[i]]+v[i], dp[i-1][j])
else:
dp[i][j]=dp[i-1][j]
return dp[-1][-1]
dp=[[0 for i in range(m+1)] for j in range(l+1)]
```
:::
#### 騎士旅行問題
:::spoiler
```python=1
dx=[2,2,-2,-2,1,1,-1,-1]
dy=[1,-1,1,-1,2,-1,2,-2]
while 1:
try:
s1,s2=input().split()
if s1==s2:
print("To get from %s to %s takes 0 knight moves."%(s1,s2))
else:
x1=ord(s1[0])-ord("a")
y1=int(s1[1])-1
x2=ord(s2[0])-ord("a")
y2=int(s2[1])-1
q=[(x1,x2,0)]
flag=False
while q:
x,y,setp=q[0][0],q[0][1],q[0][2]
q.pop(0)
for i in range(8):
nx=x+dx[i]
ny=y+dy[i]
if nx==x2 and ny==y2:
print("To get from %s to %s takes %d knight moves."%(s1,a2,sept+1))
break
if nx>=0 and nx<8 and ny>=0 and ny<8:
q.append((nx,ny,setp+1))
if flag:
break
except:
break
```
:::
#### 求最大和的子區域
:::spoiler
```python=1
#d206
a=[[0 for i in range(105)] for j in range(105)]
n=int(input())
for i in range(1,n+1):
list1=[int(i) for i in input().split()]
for j in range(1,n+1):
a[i][j]=list1[j-1]
a[i][j]+=a[i][j-1]
ans=0
for i in range(n):
for j in range(i+1,n+1):
total=0
for k in range(1,n+1):
total+=a[k][j]-a[k][i]
ans=max(ans,total)
if total<0:
total=0
print(ans)
```
:::
#### 二元樹括號輸入
:::spoiler
5(4(11(7()())(2()()))()) (8(13()())(4()(1()())))
```python=1
x=input().replace(" ","")
tree=[-1]*32
n=1
num=""
for i in range(len(x)):
if x[i] not in "()":
num+=x[i]
if x[i+1] in "()":
tree[n]=int(num)
num=""
if x[i]=="(":
if tree[2*n]==-1:
n*=2
else:
n=n*2+1
elif x[i]==")":
if tree[n]==-1:
tree[n]=0
n=int(n/2)
```
:::
#### 強連通
:::spoiler

##### Kosaraju's Algorithm
>使用DFS實作
>再進行一次DFS,並由離開DFS節點順序放入後,疊加進行DFS
>這次的dfs中,此節點能夠碰到都是同組scc
```python=1
visit=[[] for i in range(100)]
edge=[[] for i in range(100)]
rev_edge=[[] for i in range(100)]
group=[0]*101
path=[]
def dfs1(root):
global visit,group
if visit[root]==1:
return
visit[root]=1
for i in edge[root]:
dfs(i)
path.append(root)
def dfs2(root,ans):
global visit,group
if visit[root]==1:
return
visit[root]=1
group[root]=ans
for i in rev_edge[root]:
dfs2(i,ans)
def kosaraju():
global visit,group
cnt,q=map(int,input().split())
for i in range(q):
a,b=map(int,input().split())
edge[a].append(b)
rev_edge[b].append(a)
visit=[0]*(101)
path.clear()
for i in range(cnt):
if visit[i]==0:
dfs1(i)
visit=[0]*cnt
grout=[0]*cnt
for i in range(len(path)-1,-1,-1):
if visit[path[i]]==0:
dfs2(path[i],path[i])
print(group)
kosaraju()
```
:::
#### 還原樹 (BFS,DFS)
:::spoiler
```python=1
import heapq
bfs=[]
dfs=[]
n=int(input())
v=[[] for i in range(101)]
q=[]
class Seg:
def __init__(self,left,right):
self.left=left
self.right=right
def slove():
global q,v
q.append(Seg(0,n))
p=1
root=0
while len(q)>0:
s=q.pop(0)
if s.right-s.left<=1 or p==n:
continue
root=dfs[s.left]
#print(root)
pre=s.left+1
for i in range(pre,s.right):
if dfs[i]==bfs[p]:
q.append(Seg(pre,i))
v[root].append(dfs[i])
p+=1
pre=i
if pre<s.right:
q.append(Seg(pre,s.right))
bfs=[int(i) for i in input().split()]
dfs=[int(i) for i in input().split()]
slove()
for i in v:
print(i)
```
:::
#### 並查集
:::spoiler
```python=1
#f677
n,m=map(int,input().split())
parent=[int(i) for i in range(n)]
for _ in range(m):
a,b=map(int,input().split())
mx=max(parent[a],parent[b])
mn=max(parent[b],parent[a])
for i in range(len(parent)):
if parent[i]==parent[mn]:
parent[i]=parent[mx]
print(parent.count(parent[0]))
```
:::
#### 二分搜
:::spoiler
```python=1
#d732
def binary_search(list1,num):
low = 0
high = len(list1)-1
while(low<=high):
mid = (low+high)//2
guess = list1[mid]
if(guess==num):
return mid
elif(guess>num):
high = mid-1
else:
low = mid+1
return -1
```
>可以使用bisect
```python=1
import bisect
def binary_search(list1,num):
return bisect.bisect_left(list1,num)
```
:::
## :memo: 常用函式或功能
#### 以 dict value由小到大排序,若value一樣則由key 由大到小排序
```python=1
for k,v in sorted(dict1.items(),key=lambda x:(x[1],-x[0])):
print(k,v)
```
#### 增加最大遞迴深度(python 預設為1000)
``` python=1
import sys
sys.setrecursionlimit(20000)
```
#### input加快
``` python=1
m=int(sys.stdin.readline().strip())
matrix.append(list(map(int,sys.stdin.readline().strip().split(" "))))
```
#### 位元
```python=1
a=60 #60 = 0011 1100
b=13 #13 = 0000 1101
c=0
#& and 運算
c=a&b #12 0000 1100
# | or運算
c=a|b #61 0011 1101
#^ 互斥,對應的二進位相時,結果為1
c=a^b #49 0011 0001
# ~ 補數 二進位取反 1變成0 0變成1
c=~a #-61 1100 0011
# << 二進位全部向左移若干位,高位丟棄,低位補0
c=a<<2 #240 1111 0000
#>> 二進位全部向右移
c=a>>2 #15 0000 1111
print(("1<<5的結果",1<<5)) #32 100000
```
#### python 日期
``` python=1
import datetime
# 日期相減
begin=datetime.date(2022,11,29)
end=datetime.date(2022,11,12)
result=begin-end
print(str(result.days))
#17
# 日期加一天
in_date="2022-11-12"
dt=datetime.datetime.strptime(in_date,"%Y-%m-%d")
out=(dt+datetime.timedelta(days=17)).strftime("%Y-%m-%d")
print(out)
#2022-11-29
#日期減一天
in_date="2022-11-29"
dt=datetime.datetime.strptime(in_date,"%Y-%m-%d")
out=(dt-datetime.timedelta(days=17)).strftime("%Y-%m-%d")
print(out)
#2022-11-12
#求星期
a,b=map(int,input().split())
print(datetime.date(2022, a, b).strftime("%A"))
```
#### 分數加減
```python=1
#導入fractions模組
from fractions import Fraction
print(Fraction(2,9)+Fraction(1,4))
#17/36
```
#### 運算子優先權
```python=1
(), [], {}, set()
#--------
**
#--------
+x, -x, ~x
#--------
*, /, // , %
#--------
+, -
#--------
<<, >>
#--------
&
^
|
<
<=
>
>=
==
!=
in
not in
is
is not
not
and
or
if, elif, else
lambda
```
## :memo: 重要經典題目
#### DP經典問題
:::spoiler
> 給你兩個字串 S 和 T,請問 S 有多少個子序列與 T 相同呢?
input:
rabbbit
rabbit
output:
3
```python=1
s=input()
t=input()
n,m=len(s),len(t)
dp=[[0]*(m+1) for _ in range(n+1)]
dp[0][0]=1
for i in range(1,n+1):
dp[i][0]=1
for j in range(1,m+1):
if s[i-1]==t[j-1]:
dp[i][j]=dp[i-1][j]
else:
dp[i][j]=dp[i-1][j-1]+dp[i-1][j]
print(dp[n][m])
```
字串編輯問題
> 給你兩個字串 word1, word2。每一次可以插入、刪除、修改一個字元。請問至少要幾次操作才能將 word1 換成 word2 呢?
input:
horse
ros
output:
3
```python=1
word1=input()
word2=input()
dp=[list(range(i,m+i+1)) for i in range(n+1)]
for i in range(1,n+1):
for j in range(1,m+1):
if word1[i-1]==word2[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
print(dp[n][m])
```
> 給你兩個字串 str1 與 str2,找出一個最短的公共字串 S,使得 str1 與 str2 同時是 S 的子字串。
> input
> abac
> cab
> output
> cabac
```python=1
str1=input()
str2=input()
n,m=len(str1),len(str2)
dp=[[0]*(m+1) for _ in range(n+1)]
for i in range(1,n+1):
for j in range(1,m+1):
if str1[i-1]==str2[j-1]:
dp[i][j]=dp[i-1][j-1]+1
else:
dp[i][j]=max(dp[i-1][j],dp[i][j-1])
answer=""
i,j=n,m
while i>0 and j>0:
if str1[i-1]==str2[j-1]:
answer+=str1[i-1]
i,j=i-1,j-1
elif dp[i-1][j]>dp[i][j-1]::
answer+=str1[i-1]
i=i-1
else:
answer+=str2[j-1]
j=j-1
answer=answer[::-1]
print(str1[0:i]+str2[0:j]+answer)
```
:::
#### 旗立108 G 二元樹最大路徑總和
:::spoiler
``` python=1
# AC time: 0.7s
def run(n,n1,sum,p): #節點,目標節點,總和,上一個
global tree,list5
if n==n1: #如果到目標點就放在list5
list5.append(sum)
return
else:
s=0
if n%2==0:s=int(n/2) #上一個點
else:s=int((n-1)/2)
if not n==1 and p!=s : #如果上一個點不是p 也不是1 (上一個不可能是null)
run(s,n1,sum+int(tree[s]),n)
s=int(n*2) #左邊
if tree[s]!="null" and p!=s:
run(s,n1,sum+int(tree[s]),n)
s=int(n*2+1) #右邊
if tree[s]!="null" and p!=s:
run(s,n1,sum+int(tree[s]),n)
for _ in range(int(input())):
t=input()[1:-1].replace(" ","").split(",")
tree=t
tree.insert(0,"null")
for i in range(500):
tree.append("null")
list5=[]
for i in range(len(tree)):
for j in range(len(tree)):
if tree[i].isdigit() and tree[j].isdigit():
run(i,j,int(tree[i]),-1)
if len(list5)==0:
print(-1)
else:
print(max(list5))
```
``` python=1
#AC time: 19ms
def dfs(n, path=[]):
path.append(int(tree[n]))
r=0
if n*2+1<=max_node:
if tree[n*2+1]!='null':
dfs(n*2+1, path.copy())
r+=1
if n*2+2<=max_node:
if tree[n*2+2]!='null':
dfs(n*2+2, path.copy())
r+=1
if r==0: #到leaf了...
lst.append(sum(path))
for _ in range(int(input())):
tree=input().replace(' ','').replace('[','').replace(']','').split(',')
max_node=len(tree)-1 #處理邊界,避免出現溢位
ans=[]
for i in range(len(tree)):
if tree[i]=='null':
continue
lst=[]
L=0
R=0
if i*2+1<=max_node and tree[i*2+1]!='null':
dfs(i*2+1,[])
if lst!=[]:
L=max(max(lst),0) #如果max(lst)<0, 那就不能走, 不然路徑和會變小
lst.clear() #清空
if i*2+2<=max_node and tree[i*2+2]!='null':
dfs(i*2+2,[])
if lst!=[]:
R=max(max(lst),0) #如果max(lst)<0, 那就不能走, 不然路徑和會變小
ans.append(int(tree[i])+L+R)
print(max(ans))
```
:::
#### 二元一次方程式 103 B 郵票
:::spoiler

```python=1
for _ in range(int(input())):
p,c,d,q=map(int,input().split(","))
x=(d*p-q)/(d-c)
y=(c*p-q)/(c-d)
print("%d,%d"%(x,y))
```
:::
#### 110模擬 G格雷碼
:::spoiler
``` python=1
def f(x):
g=['0','1']
for i in range(1, x):
a=[]
b=[]
for j in g:
a.append('0'+j)
g=g[::-1]
for j in g:
b.append('1'+j)
g=a+b
return g
n=int(input())
ans=f(n)
for i in ans:
print(i)
```
:::
#### 110 條條大路通羅馬
:::spoiler
``` python=1
def DFS(x):
visited[x]=1
for i in path[x]:
if visited[i]==0:
DFS(i)
n,m=map(int, input().split())
path=[[] for i in range(n+1)]
visited=[0]*(n+1)
for _ in range(m):
a,b=map(int, input().split())
path[a].append(b)
A,B=map(int, input().split())
DFS(A)
if visited[B]==1:
print('Yes')
else:
print('No')
```
:::
#### 111 T路徑
:::spoiler
``` python=1
from collections import deque
def treepath(node,order):
if node>l or tree[node]=="null":
return
order.append(tree[node])
if 2*node+1>l or (tree[2*node+1]=="null" and tree[2*node+2]=="null"):
path="->".join(list(order))
print(path)
treepath(2*node+1,order)
treepath(2*node+2,order)
order.pop()
tree=input().split()
l=len(tree)-1
path=deque()
treepath(0,path)
```
:::
#### 111 E1 建樹
:::spoiler
``` python=1
while 1:
try:
dic={}
f=False; Tree=True
while 1:
s=input().split()
for i in s:
if i=='()':
f=True
else:
a,b=i[1:len(i)-1].split(',')
if b=='':
b='root'
if b in dic:
Tree=False
dic[b]=a
if f:
break
if 'root' not in dic:
Tree=False
if Tree:
tree=[]
tree.append(dic['root'])
del dic['root']
q=['L','R']
while q:
node=q.pop(0)
if node in dic:
tree.append(dic[node])
q.append(node+'L')
q.append(node+'R')
del dic[node]
if len(dic)>0:
print('not complete')
elif not Tree:
print('not complete')
else:
print(*tree)
except:
break
```
:::
#### 111 E2 迷宮
:::spoiler
``` python=1
import heapq
import sys
ntiem=int(input())
inf=(1000000)*9
direct=(0,1,0,-1,0)
for i in range(ntiem):
m=int(sys.stdin.readline().strip())
n=int(sys.stdin.readline().strip())
matrix=[]
m_1=range(m+1)
n_1=range(n+1)
for j in m_1[0:-1]:
matrix.append(list(map(int,sys.stdin.readline().strip().split())))
values=[[inf for a in n_1] for b in m_1]
values[0][0]=matrix[0][0]
pq=[]
heapq.heappush(pq,(values[0][0],0,0))
while pq:
value,x,y=heapq.heappop(pq)
for c in range(4):
nx,ny=direct[c]+x,dicect[c+1]+y
if nx<0 or ny<0 or nx>=n or ny>=m:
continue
val=value+matrix[ny][mx]
if values[ny][nx]>val:
values[ny][nx]=val
heapq.heappush(pq,[val,nx,ny])
sys.stdout.write(f"{values[m-1][n-1]}\n")
```
:::
#### 河內塔
:::spoiler
``` python=1
def hanoi_tower(n,v,m,t):
if n==1:
print('Move ring',n,'from',v,'to',t) #n從 v點移到t點
else:
hanoi_tower(n-1,v,t,m)
print('Move ring',n,'from',v,'to',t)
hanoi_tower(n-1,m,v,t)
n=int(input())
hanoi_tower(n,'A','B','C')
```
>河內塔變種(奇數放在b柱,偶數放在c柱)
``` python=1
#b190
#全放
ansa = 0
def f(num,a,b,c):
global ansa
if(num<=1):
temp = dic[a].pop()
print("ring %d : "%temp,end = "")
dic[c].append(temp)
print(a,"->",c)
ansa+=1
else:
f(num-1,a,c,b)
f(1,a,b,c)
f(num-1,b,a,c)
#放一半
def g(num,a,b,c):
global ansa
if(num!=1):
f(num-1,a,c,b)
temp = dic[a].pop()
print("ring %d : "%temp,end = "")
dic[c].append(temp)
print(a,"->",c)
ansa+=1
def ans(num,a,b,c):
i=0
while(num>0):
g(num,a,b,c)
if(i==0):
a,b = b,a
num-=2
i=1
else:
a,b,c = b,c,a
num-=1
i=0
try:
while(1):
dic = {}
ansa = 0
n = int(input())
dic["a"] = [i for i in range(n+1,0,-1)]
dic["b"] = []
dic["c"] = []
if(n%2==1):
ans(n,"a","c","b")
else:
ans(n,"a","b","c")
print("共移動了",ansa,"步")
except EOFError:
pass
```
>河內塔變種-在無法枚舉全部情況(數字給很大)的情況下求出第n步移動情況
``` python=1
#e790求n盤河內塔第m步的移動情況
point1 = [2,3,1]
point2 = [3,2,1]
a,b = map(int,input().split())
ans = (bin(b)[2:][::-1]).index("1")+1
ans2 = 0
if(a%2==0):
point1,point2 = point2,point1
for j in range(ans-1):
ans2 = ans2*2+1
if(ans%2==0):
lans1 = point1[((b-ans2)//2**ans)%3]
lans2 = point1[(((b-ans2)//2**ans)%3-1)%3]
else:
lans1 = point2[((b-ans2)//2**ans)%3]
lans2 = point2[(((b-ans2)//2**ans)%3-1)%3]
print("move %d from %d to %d"%(ans,lans2,lans1))
```
:::
#### 104 F 矩陣相乘
求9999
:::spoiler
``` python=1
for _ in range(int(input())):
m,r,r1,n=map(int,input().split(","))
lista=[]
for i in range(m):
lista.append([int(i) for i in input().split()])
listb=[]
for i in range(r1):
listb.append([int(i) for i in input().split()])
listc=[]
for i in range(m):
listc.append([int(i) for i in input().split()])
INF=100000000
check=INF #ans
for i in range(m):
if 9999 in lista[i]: #如果9999在lista中
lista999=lista[i].index(9999) #找出lista的位置
for k in range(n): #找出listb相對位置
if listb[lista999][k]!=0: #相對位置不是0 如果是0相乘就是0 沒有意義
sum1=0
for j in range(r): #這裡開始相乘
if lista[i][j]==9999: #如果是9999 就把相對位置記錄起來
ans1=listb[j][k]
else:
sum1+=listb[j][k]*lista[i][j] #不是就相乘
check=(listc[i][k]-sum1)/ans1 #透過C求解
if check!=INF: #如果不是10000代表算出答案 那就可以離開
break
if check==INF: #如果還是10000代表9999不再a中,從b找
newb=[] #翻轉一下比較方便
for i in range(n):
newb.append([])
for j in range(r1):
newb[i].append(listb[j][i])
#完成反轉
for i in range(len(newb)): #跟a差不多
if 9999 in newb[i]:
t=newb[i].index(9999)
for k in range(m):
if lista[k][t]!=0:
ans1=0
sum1=0
for gg in range(r):
if newb[i][gg]==9999:
ans1=lista[k][gg]
else:
sum1+=lista[k][gg]*newb[i][gg]
check=(listc[k][i]-sum1)/ans1
if check!=INF:
break
if check!=INF:
break
print(int(check))
```
:::
#### 最大連續和
:::spoiler
```python=1
list1=[int(i) for i in input().split()]
sum=0
mx=-1e9
for i in range(len(list1)):
sum+=list1[i]
mx=max(sum,mx)
if sum<0:
sum=0
print(mx)
```
:::
#### 103 E 撲克牌
:::spoiler
``` python=1
from itertools import combinations
def dfs(tmp): #判斷同色
end=0
for i in tmp:
if not(i<14):
break
else:
end=1
if end==0:
for i in tmp:
if not(i>13 and i<27):
break
else:
end=1
if end==0:
for i in tmp:
if not(i>26 and i<40):
break
else:
end=1
if end==0:
for i in tmp:
if not(i>39):
break
else:
end=1
return end
for _ in range(int(input())):
list1=[int(i) for i in input().split()]
list2=list(combinations(list1,5))
ans=[]
t=0
for i in list2:
tmp=i
tmp=sorted(tmp)
end=0
s=0
rrr=0
if dfs(tmp)==1: #符合同色 判斷連續
for i in range(1,len(tmp)):
if tmp[i]-tmp[i-1]==1:
s+=1
if s==4:
t=7
end=1
s=0
if (tmp[0]-1)%13==0: #A換成14
tmp[0]+=13
tmp.sort()
for i in range(1,len(tmp)):
if tmp[i]-tmp[i-1]==1:
s+=1
if s==4:
t=7
end=1
if end==0:
sorttmp=[]
for i in tmp:
if i<14:
sorttmp.append(i)
elif i<27:
sorttmp.append(i-13)
elif i<40:
sorttmp.append(i-26)
else:
sorttmp.append(i-39)
for i in sorttmp:
if sorttmp.count(i)==4:
t=6
end=1
break
if end==0:
three=0
two=0
for i in sorttmp:
if sorttmp.count(i)==2:
two+=1
if sorttmp.count(i)==3:
three+=1
if two==2 and three==3:
t=5
end=1
if end==0:
if three==3:
t=3
end=1
if two==4:
t=2
end=1
if two==2:
t=1
end=1
if end==0:
s=0
sorttmp.sort()
for i in range(1,len(sorttmp)):
if sorttmp[i]-sorttmp[i-1]==1:
s+=1
if s==4:
t=4
end=1
else:
s=0
if 1 in sorttmp:
sorttmp[sorttmp.index(1)]=14
sorttmp.sort()
for i in range(1,len(sorttmp)):
if sorttmp[i]-sorttmp[i-1]==1:
s+=1
if s==4:
t=4
end=1
ans.append(t)
print(max(ans))
```
:::
#### 108旗立H 求完全平方數有幾個
:::spoiler
> Lagrange 四平方和定理: 任何一个正整数都可以表示成不超过四个整数的平方之和。
> 满足四数平方和定理的数n(这里要满足由四个数构成,小于四个不行),必定满足 n = 4a ( 8 b + 7 )
``` python=1
# TLE time:6s
def f(n):
cnt=n
num=2
while num*num>=n:
a=n/(num*num)
b=n%(num*num)
cnt=min(cnt,a+f(b))
num+=1
return cnt
for _ in range(int(input())):
n=int(input())
print(int(f(n)))
#AC time:19ms
def num(n):
while n%4==0:
n//=4
if n%8==7: #7=4+1+1+1
return 4
for i in range(n+1):
tmp=i*i
if tmp<=n:
if (int(n-tmp)**0.5)**2+tmp==n:
return 1+(0 if tmp==0 else 1)
else:
break
return 3
for _ in range(int(input())):
print(num(int(input())))
```
:::
#### 105旗立E 最小成本生成樹及次小生成樹
:::spoiler
> 次小生成樹求法為: 先刪去每個邊求最小成本,裝進list中,若最小生成樹大於list的一半他就是次小,如果沒有那就將不是最小的裝進list2中,再找min
``` python=1
import heapq
import copy
for _ in range(int(input())):
#求最小生成樹
instr=input().split()
parent=[0]*1001
num=[1]*1001
pq=[]
def findparent(a):
if a not in city.keys():
city[a]=len(city)
return city[a]
city={}
def getcityindex(p):
if p not in city.keys():
city[p]=len(city)
return city[p]
m=len(instr)
for i in range(m):
s=instr[i]
a,b,c=s.split(",")
w=int(w)
a=getcityindex(a)
b=getcityindex(b)
heapq.heapppush(pq,(w,a,b))
n=len(city)
for i in range(1001):
parent[i]=i
i=numEdge=result=0
while i<m and numEdge<n:
edge=heapq.heappop(pq)
a=findparent(edge[1])
b=findparent(edge[2])
if a!=b:
if num[a]>num[b]:
parent[b]=a
num[a]+=num[b]
else:
parent[a]=b
num[b]+=num[b]
numEdge+=1
result+=int(edge[0])
i+=1
ans1=result
# 最小生成樹到此結束
anslist=[] #求次小生成樹
for i in range(m):
newinstr=copy.deepcopy(instr)
del newinstr[i]
#以下求法跟上面一樣
parent=[0]*1001
num=[1]*1001
pq=[]
def findparent(a):
while a!=parent[a]:
parent[a]=a
return a
city={}
def getcityindex(p):
if p not in city.keys():
city[p]=len(city)
return city[p]
m=len(newinstr)
for i in range(m):
s=newinstr[i]
a,b,w=s.split(",")
w=int(w)
a=findparent(a)
b=findparent(b)
heapq.heapppush(pq,(w,a,b))
n=len(city)
for i in range(1001):
parent[i]=i
i=numEdge=rseult=0
while i<m and numEdge<n:
edge=heapq.heappop(pq)
a=findparent(edge[1])
b=findparent(edge[2])
if a!=b:
if num[a]>num[b]:
parent[b]=a
num[a]+=num[b]
else:
parent[a]=b
num[b]+=num[a]
numedge+=1
result+=int(edge[0])
i+=1
ans.append(result)
#次小生成樹求法到此結束,以下開始判斷
if anslist.count(ans1)>len(anslist1)//2:
print(ans1,ans1)
else:
newans=[]
for i in anslist:
if i!=ans1:
newans.append(i)
if len(newans)==0: #不太會有這個可能,但還是判斷一下
print(ans1,ans2)
else:
print(ans1,min(newans1))
```
:::
#### a249: 00679 - Dropping Balls
:::spoiler
``` python=1
for _ in range(int(input())):
D,I=map(int, input().split())
idx=1
remainder=I
for i in range(D-1):
if remainder%2==1:
idx=2*idx
remainder=(remainder+1)//2 #remainder餘數
else:
idx=2*idx+1
remainder//=2
print(idx)
```
:::
#### 110群科Q8 交換物品
:::spoiler

``` python=1
I=[]
vertex=[]
inf=99999
while 1:
try:
x=input().split()
I.append(x)
vertex.append(x[0])
vertex.append(x[1])
except:
break
vertex=[0]+(list(set(vertex)))
start=vertex.index(I[0][0])
end=vertex.index(I[-2][-2])
I.pop()
n=len(vertex)
m=len(I)
visited=[0 for i in range(n+1)]
data=[[inf for i in range(n+1)] for j in range(n+1)]
dis=[inf for i in range(n+1)]
visited[start]=1
for i in range(1,n+1):
for j in range(1,n+1):
if i==j:
data[i][j]=0
for i in range(m):
data[vertex.index(I[i][0])][vertex.index(I[i][1])]=int(I[i][2])
for i in range(1,n+1):
dis[i]=data[start][i]
paths=[start for i in range(n+1)]
for i in range(n):
minn=inf
for j in range(1,n+1):
if visited[j]==0 and minn>dis[j]:
minn=data[i][j]
u=j
visited[u]=1
for j in range(1,n+1):
if dis[j]>dis[u]+data[u][j]:
dis[j]=dis[u]+data[u][j]
paths[j]=u
print(dis[end])
whlk=[end]
k=end
while k!=start:
k=paths[k]
walk.append(k)
for i in walk[::-1]:
print(vertex[i],end=" ")
```
:::
#### 連續加總
:::spoiler
```python=1
#UVA 11254
def check(n,r):
a=2*n+r-r**2
if a%(2*r)==0:
return (a/(2*r))
return -1
n=int(input())
while n>0:
m=int((2*n)**0.5)
p=0
for i in range(m,0,-1):
a=check(n,i)
if a!=-1:
print("%d = %d + ... + %d"%(n,a,a+i-1))
break
n=int(input())
```
:::
#### 矩陣快速冪
:::spoiler
>本方法可使O(n)降為O(log n)
```python=1
#ZJ-a451,TA001-TB01
#返回兩個2*2矩陣相乘結果
def arrmult(arr1,arr2,m):
ansarr = [[0,0],[0,0]]
ansarr[0][0]=(arr1[0][0]*arr2[0][0]+arr1[0][1]*arr2[1][0])%m
ansarr[0][1]=(arr1[0][0]*arr2[0][1]+arr1[0][1]*arr2[1][1])%m
ansarr[1][0]=(arr1[1][0]*arr2[0][0]+arr1[1][1]*arr2[1][0])%m
ansarr[1][1]=(arr1[1][0]*arr2[0][1]+arr1[1][1]*arr2[1][1])%m
return ansarr.copy()
#矩陣快速冪
def fastmult(arr,b,m):
if(b<=1):
return arr
if(b%2==0):
return fastmult(arrmult(arr,arr,m),b//2,m)
return arrmult(arr,fastmult(arrmult(arr,arr,m),b//2,m),m)
def fib(n,m):
if(n==0):
return 0
if(n==1):
return 1
if(n==2):
return 1
fibarr = [[1,1],[1,0]]
theans = fastmult(fibarr,n-2,m)
return (theans[0][0]+theans[0][1])%m
try:
while(1):
n,m = map(int,input().split())
print(fib(n,2**m))
except EOFError:
pass
```
:::
#### 輸入整數轉羅馬符號
:::spoiler
```python=1
n=int(input())
for i in range(n):
num = int(input())
if 1 <= num <= 3999:
val = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
syb = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"]
roman_num = ''
i = 0
while num > 0:
if num >= val[i]:
roman_num += syb[i]
num -= val[i]
else:
i += 1
print(roman_num)
```
:::
#### 輸入羅馬符號轉整數
:::spoiler
```python=1
roman_numerals = ["I", "V", "X", "L", "C", "D", "M"]
integer_values = [1, 5, 10, 50, 100, 500, 1000]
roman_numeral = input()
total = 0
prev_value = 0
for numeral in roman_numeral:
value = integer_values[roman_numerals.index(numeral)]
if value > prev_value:
total += value - 2 * prev_value
else:
total += value
prev_value = value
print(total)
```
:::
#### 108正式-F 循環小數
:::spoiler
```python=1
t = int(input())
for _ in range(t):
a,b = map(int,input().split())
num = a%b
arr1 = [num]
arr2 = []
while(1):
arr2.append((10*num)//b)
num = (10*num)%b
if(num in arr1):
ansindex = arr1.index(num)
break
arr1.append(num)
print(a//b,end = ".")
if(len(arr2[ansindex:])>50):
print(*arr2[:ansindex],"(",*arr2[ansindex:ansindex+50],"...)",sep = "")
else:
print(*arr2[:ansindex],"(",*arr2[ansindex:],")",sep = "")
```
:::
#### 點圖
:::spoiler
#### 求平行四邊形
給定平行四邊形的兩個相鄰邊的端點的 (x, y)座標。
找到第四個點的 (x, y)座標。
```python=1
while 1:
try:
except:
list1=[eval(i) for i in input().split()]
list3=[]
list3.append(list1[0],list1[1])
list
break
]=999999
print(sum)
```
:::
#### 高精度運用
:::spoiler
>大數-所有大數運算都可以變更快速(尤其是計算冪次和取餘的部分
```python=1
#e036
from decimal import *
setcontext(Context(prec=MAX_PREC,Emax=MAX_EMAX))
#計算2^82589933
a = Decimal(2)
b = Decimal(82589933)
print(a**b)
```
:::
#### 喬瑟夫問題
:::spoiler
```python=1
#d192
def josephus(n,k):
#遞迴在數字太大的時候容易炸開,遞推比較保險
survivor = 0
for i in range(2, n + 1):
survivor = (survivor+k)%i
return survivor+1
t = int(input())
for i in range(t):
print("Case %d: " % (i+1), end="")
n, k = map(int, input().split())
print(josephus(n,k))
```
:::
## :memo: 賽前重點刷題
[a676](https://zerojudge.tw/ShowProblem?problemid=a676) -LIS
[f168](https://zerojudge.tw/ShowProblem?problemid=f168) -分配寶物
[d536](https://zerojudge.tw/ShowProblem?problemid=d536) -圖形迴圈偵錯
[d768](https://zerojudge.tw/ShowProblem?problemid=d768) -DFS
[c001](https://zerojudge.tw/ShowProblem?problemid=c001) -LCS
[c547](https://zerojudge.tw/ShowProblem?problemid=c547) -DP 爬樓梯
[e544](https://zerojudge.tw/ShowProblem?problemid=e544) -DNA sort
[d908](https://zerojudge.tw/ShowProblem?problemid=d908) -最佳路徑
[b537](https://zerojudge.tw/ShowProblem?problemid=b537) -分數運算
[d378](https://zerojudge.tw/ShowProblem?problemid=d378) -最小路徑 地圖
[d192](https://zerojudge.tw/ShowProblem?problemid=d192) -喬瑟夫
[c350](https://zerojudge.tw/ShowProblem?problemid=c350) - 數學
[c317](https://zerojudge.tw/ShowProblem?problemid=c317) - 硬幣問題
[e339](https://zerojudge.tw/ShowProblem?problemid=e339) - 前綴和
[a982](https://zerojudge.tw/ShowProblem?problemid=a982) - 迷宮問題
[b184](https://zerojudge.tw/ShowProblem?problemid=b184) - 背包
[d904](https://zerojudge.tw/ShowProblem?problemid=d904) - 硬幣
[d637](https://zerojudge.tw/ShowProblem?problemid=d637) - 背包
[c117](https://zerojudge.tw/ShowProblem?problemid=c117) - 騎士旅行問題
[c126](https://zerojudge.tw/ShowProblem?problemid=c126) - 前中轉後
[a410](https://zerojudge.tw/ShowProblem?problemid=a410) - 解方程式
[f671](https://zerojudge.tw/ShowProblem?problemid=f671) - 最短路徑
[f678](https://zerojudge.tw/ShowProblem?problemid=f678) - 最小生成樹
[f673](https://zerojudge.tw/ShowProblem?problemid=f673) - 樹高
[d453](https://zerojudge.tw/ShowProblem?problemid=d453) - 最短距離
[b674](https://zerojudge.tw/ShowProblem?problemid=b674) - is it a tree
[a129](https://zerojudge.tw/ShowProblem?problemid=a129) - 最小生成樹
[f675](https://zerojudge.tw/ShowProblem?problemid=f675) - BST
[d526](https://zerojudge.tw/ShowProblem?problemid=d526) - BST
[f698](https://zerojudge.tw/ShowProblem?problemid=f698) - 後序運算
[d862](https://zerojudge.tw/ShowProblem?problemid=c126) - 背包
[a252](https://zerojudge.tw/ShowProblem?problemid=a252) - LCS
[a445](https://zerojudge.tw/ShowProblem?problemid=a445) - 並查集
[e586](https://zerojudge.tw/ShowProblem?problemid=e586) - 最小生成樹
[f291](https://zerojudge.tw/ShowProblem?problemid=f291) - 試算表
[e626](https://zerojudge.tw/ShowProblem?problemid=f291) - 連續和
## :memo: 函式研究與筆記暫存(會調整或刪除)
#### 內建函式
:::spoiler
```python=1
#本地x,y,z,a,b代表數字,list開頭代表陣列,s代表字串,c代表單一字元,func代表函式
abs(x) #取絕對值
bin(x) #數字轉二進位
hex(x) #數字轉16進位
int(s,b) #把某進位轉換成10進位
chr(x) #回傳對應ASCII碼的文字
ord(c) #回傳此字元的ASCII碼
```
:::