https://hihocoder.com/contest/offers74/problem/2
题目2 : 取球游戏
思路:union-find,同一个x对应的点连在一起,同一个y对应的点连在一起,并且一个联通区域最后一定可以只剩下一个点
n=int(raw_input())
a=[]
for i in range(n):
t=map(int,raw_input().strip().split(' '))
a.append((t[0],t[1],i))
fa=list(xrange(n))
def find(p):
while fa[p]!=p: p=fa[p]
return p
def union(p,q):
fa[find(p)]=find(q)
a.sort()
for i in range(1,n):
if a[i][0]==a[i-1][0]: union(a[i][2],a[i-1][2])
a.sort(key=lambda t:t[1])
for i in range(1,n):
if a[i][1]==a[i-1][1]: union(a[i][2],a[i-1][2])
res=n
for i,v in enumerate(fa):
if i==v: res-=1
print res
https://hihocoder.com/contest/offers70/problem/3
题目3 : 拼三角形
思路:排序,然后从小到大遍历,能组成就标记为用过,可AC
n=int(raw_input())
a=map(int,raw_input().strip().split(' '))
res=0
a.sort()
vis=[False]*n
for i in range(n):
if vis[i]: continue
ok=False
for j in range(i+1,n):
if vis[j]: continue
for k in range(j+1, n):
if vis[k]: continue
if a[i]+a[j]>a[k]:
vis[i]=vis[j]=vis[k]=True
res+=1
ok=True
if ok: break
if ok: break
print res
更严谨的方法是状压DP
先讲一下状压dp好了。它通常使用在n十分小的情况下(比如n<=20),虽然是指数级别的复杂度,但速度比搜索快,其思想非常之优秀。所以看到n非常小时,就要想到99%是状压dp。
状压dp的适用情况就是当状态可以由0或者1来表示时,我们所需状态数组无法满足。将状态表示成二进制数转化成十进制通过位运算的处理来进行状态的转移。所以位运算在状压dp中有着重要的作用。
n=int(raw_input())
a=map(int,raw_input().strip().split(' '))
a.sort()
b=[]
for i in range(n):
for j in range(i+1,n):
for k in range(j+1,n):
if a[i]+a[j]>a[k]:
b.append((1<
这里要先构造所有的3元数组合,用来状态转移
https://hihocoder.com/contest/offers69/problem/2
题目2 : 特工配对
用优先队列是OK的,或者数学上理解一下的话,可以发现如果最大值小于sum的一半的话,一定是可以全部match的
import heapq
n=int(raw_input())
a=map(int,raw_input().strip().split(' '))
pq=[-t for t in a]
heapq.heapify(pq)
res=0
while len(pq)>1:
if len(pq)==2:
res+=-min(pq)
break
m1,m2=-heapq.heappop(pq),-heapq.heappop(pq)
if m1==m2:
res+=m1
continue
m3=-pq[0]
t=m2-m3+1
res+=t
if m1-t>0: heapq.heappush(pq, -(m1-t))
if m2-t>0: heapq.heappush(pq, -(m2-t))
print res
n=int(raw_input())
a=map(int,raw_input().strip().split(' '))
ma=max(a)
su=sum(a)
if ma*2<=su:
print su//2
else:
print su-ma
https://hihocoder.com/contest/offers69/problem/3
题目3 : 阶乘问题
思路:直接求有多少个k的因子是错误的,比如20!有多少个10,其中2和5可以组合起来弄成一个10,所以应该先因式分解,然后求每个因子有多少个
n,k=map(int,raw_input().strip().split(' '))
d={}
for i in range(2,k+1):
if i*i>n: break
while k%i==0:
d[i]=d.get(i,0)+1
k//=i
if k!=1: d[k]=d.get(k,0)+1
def cal(t,s):
cnt=0
while t:
cnt+=t//s
t//=s
return cnt
res=float('inf')
for k in d:
t=cal(n,k)
res=min(res, t//d[k])
print(res)