蓝桥杯题库
- 入门训练
- 历届试题
- 省赛
- 杨辉三角形【第十二届】【省赛】【研究生组】(!!!)
- 错误票据【第四届】【省赛】【A组】
- 买不到的数目【第四届】【省赛】【A组】(数论)
- 剪格子【第四届】【省赛】【A组】(dfs)
- 大臣的旅费【第四届】【省赛】【A组】(!数的直径dfs,重写)
- 带分数【第四届】【省赛】【A组】(!!!!dfs)
- 网络寻路【第四届】【决赛】【A组】
- 蚂蚁感冒【第五届】【省赛】【A组】(思维:较易)
- 地宫取宝【第五届】【省赛】【A组】(记忆化搜索:适中)
- 斐波那契【第五届】【省赛】【A组】(斐波那契的矩阵快速幂求法:较难)
- 波动数列【第五届】【省赛】【A组】(DP:难!)
- 兰顿蚂蚁【第五届】【省赛】【A组】(模拟:易)
- 移动距离【第六届】【省赛】【A组】(思维:易)
- 灾后重建【第六届】【省赛】【A组】(kruskal最小生成树,....难!!)
- 垒骰子【第六届】【省赛】【A组】(DP+矩阵优化,较难)
- 饮料换购【第六届】【省赛】【A组】(思维,易)
- 交换瓶子【第七届】【省赛】【A组】(思维,易)
- 压缩变换【第七届】【省赛】【A组】
- 取球博弈【第七届】【省赛】【A组】(博弈论,dfs)
- 最大比例【第七届】【省赛】【A组】(数论,最大公约数,辗转相减法)
- 密码脱落【第七届】【省赛】【A组】(DP:LCS)
- 四平方和【第七届】【省赛】【A组】(枚举+哈希)
- 油漆面积【第八届】【省赛】【A组】(线段树,扫描线,离散化,矩形面积并)
- 分巧克力【第八届】【省赛】【A组】(二分)
- 包子凑数【第八届】【省赛】【A组】(DP+数论)
- 正则问题【第八届】【省赛】【A组】
- 结账问题【第九届】【省赛】【A组】(贪心)
- 倍数问题【第九届】【省赛】【A组】
- 全球变暖【第九届】【省赛】【A组】
- 三体攻击【第九届】【省赛】【A组】
- 航班时间【第九届】【省赛】【A组】
- 决赛
入门训练
A+B问题
a,b=map(int,input().split())
print(a+b)
数列排序
n=int(input())
a=[int(x) for x in input().split()]
a=sorted(a)
for x in a:
print(x,end=' ')
十六进制转八进制
n=int(input())
for i in range(n):
t=input()
print("{:o}".format(int(t,16)))
十六进制转十进制
t=input()
print(int(t,16))
十进制转十六进制
t=input()
print("{:X}".format(int(t)))
特殊回文数
def getsum(x):
sums=0
num=str(x)
for i in range(len(num)):
sums+=int(num[i])
return sums
def rev(x):
s1=str(x)
if s1==s1[::-1]:
return True
else :
return False
n=int(input())
for x in range(10000,1000000):
if rev(x) and getsum(x)==n :
print(x)
# 判断回文数的操作放在左边否则会超时
回文数
def rev(x):
s1=str(x)
if s1==s1[::-1]:
return True
else :
return False
for x in range(1000,10000):
if rev(x) :
print(x)
特殊的数字
def fun(x):
s=str(x)
res=0
for i in s:
res+=int(i)**3
if res==x:
return True
else :
return False
for x in range(100,1000):
if fun(x):
print(x)
杨辉三角形
n=int(input())
a=[[1 for x in range(n+1)]for x in range(n+1)]
for i in range(n):
for j in range(i+1):
if j==0 or j==i or i==0:
print(1,end=' ')
else:
a[i][j]=a[i-1][j]+a[i-1][j-1]
print(a[i][j],end=' ')
print()
查找整数
n=int(input())
li=list(map(int,input().split()))
a=int(input())
if a in li:
ind=li.index(a)
print(ind+1)
else:
print(-1)
数列特征
n=int(input())
a=[int(x) for x in input().split()]
print(max(a))
print(min(a))
print(sum(a))
字母图形
def is_ans(n, m):
graph = [[0 for j in range(m)] for i in range(n)]
for i in range(n):
for j in range(m):
if j >= i:
graph[i][j] = chr(ord('A')+ j - i)
else:
graph[i][j] = chr(ord('A') + i - j)
return graph
if __name__ == '__main__':
n, m = map(int, input().split())
gragh = is_ans(n ,m)
for i in range(n):
for j in range(m):
print(gragh[i][j], end='')
print()
01字串
for i in range(32):
print("{:b}".format(i).zfill(5))
闰年判断
y=int(input())
if (y%4==0 and y%100!=0) or y%400==0:
print("yes")
else :
print("no")
Fibonacci斐波那契数列
n=int(input())
#注意特判
if n==1 or n==2:
print(1)
else :
f1=f2=1
for i in range(3,n+1):
fn=(f1+f2)%10007
f1=f2%10007
f2=fn%10007
print(fn)
圆的面积
import math
r=int(input())
area=r*r*math.pi
print("%.7f"% area)
序列求和
n=int(input())
print(int((1+n)*n/2))
阶乘计算
n=int(input())
ans=1
for i in range(2,n+1):
ans*=i
print(ans)
高精度加法
a=int(input())
b=int(input())
print(a+b)
Huffuman树
n=int(input())
s=list(map(int,input().split()))
res=0
while len(s)>1:
s.sort()
t=s[0]+s[1]
# print(t)
res+=t
s.pop(0)
s.pop(0)
s.append(t)
print(res)
2n皇后问题(写的不好,记得重写)
def check(x,y,s):
if x>=n or x<0 or y>=n or y<0 :
return False
if vis[x][y]==0 :
return False
if s=='black':
if y in blackcol:
return False
else:
for i in range(len(blackcol)):
if (i-blackcol[i])==(x-y) or i+blackcol[i]==x+y:
return False
elif s=='white':
if y in whitecol:
return False
else:
for i in range(len(whitecol)):
if (i-whitecol[i])==(x-y) or i+whitecol[i]==x+y:
return False
return True
def placewhite(row):
global n,vis,resnum
if row==n:
if len(whitecol)==n:
for i in range(len(blackcol)):
if blackcol[i]==whitecol[i]:
return False
resnum+=1
else :
return False
for y in range(n):
if check(row,y,'white'):
vis[row][y]=0,whitecol.append(y)
placewhite(row+1)
vis[row][y]=1,whitecol.pop(-1)
def placeblack(row):
global n,vis,resnum
if row==n:
if len(blackcol)==n and placewhite(0):
return True
else :
return False
for y in range(n):
if check(row,y,'black'):
vis[row][y]=0,blackcol.append(y)
placeblack(row+1)
vis[row][y]=1,blackcol.pop(-1)
n=int(input())
resnum=0
vis=[[0 for x in range(n)]for x in range(n)]
blackcol=[]
whitecol=[]
for i in range(n):
vis[i]=[int(x) for x in input().split()]
vis=list(vis)
placeblack(0)
print(resnum)
报时助手
dic= {0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five', 6: 'six', 7: 'seven', 8: 'eight', 9: 'nine',
10: 'ten', 11: 'eleven', 12: 'twelve', 13: 'thirteen', 14: 'fourteen', 15: 'fifteen', 16: 'sixteen',
17: 'seventeen', 18: 'eighteen', 19: 'nineteen', 20: 'twenty', 21: 'twenty one', 22: 'twenty two',
23: 'twenty three', 30: 'thirty', 40: 'forty', 50: 'fifty'}
h,m=map(int,input().split())
if m==0 :
print(dic[h]+" o'clock")
else:
print(dic[h],end=' ')
if m in dic:
print(dic[m])
else :
t2=m%10
t1=m-t2
print(dic[t1]+' '+dic[t2])
回形取数
m,n=map(int,input().split())
a=[[0 for x in range(n)]for x in range(m)]
for i in range(m):
a[i]=[x for x in input().split()]
a=list(a)
i=0
j=0
ans=0
while ans<m*n:
while i<m and a[i][j]!=None:
ans+=1
print(a[i][j],end=' ')
a[i][j]=None
i+=1
i-=1
j+=1
while j<n and a[i][j]!=None:
ans+=1
print(a[i][j],end=' ')
a[i][j]=None
j+=1
j-=1
i-=1
while i>=0 and a[i][j]!=None:
ans+=1
print(a[i][j],end=' ')
a[i][j]=None
i-=1
i+=1
j-=1
while j>=0 and a[i][j]!=None:
ans+=1
print(a[i][j],end=' ')
a[i][j]=None
j-=1
j+=1
i+=1
龟兔赛跑预测(有问题重做)
####通过率82%,不知道哪里错了
[v1,v2,t,s,l]=map(int,input().split())
ans1=0
ans2=0
time=0
while ans1<l and ans2<l:
ans1+=v1
ans2+=v2
time+=1
if ans1==l or ans2==l:
break;
if ans1-ans2>=t:
if l-ans2>=v2*s:
ans2+=v2*s
time+=s
else :
ans
if ans1>ans2:
print("R")
elif ans2>ans1:
print("T")
else:
print("D")
print(time)
芯片测试(?)
n=int(input())
test = [[]*n]*n
for i in range(n):
test[i] = [int(j) for j in input().split()]
for j in range(n):
tra = 0
for i in range(n):
if test[i][j]==1:
tra +=1
if tra > int(n/2):
print(j+1,sep=' ',end=' ')
FJ的字符串
def fun(x):
if x==1:
return 'A'
else :
return fun(x-1)+chr(ord('A')+x-1)+fun(x-1)
n=int(input())
print(fun(n))
Sine之舞(!)
def sn(x):
global n
if x==1:
return an(1)+"+"+str(n-x+1)
else :
return '('+sn(x-1)+')'+an(x)+"+"+str(n-x+1)
def an(x):
if x==1:
return "sin("+str(x)+')'
else:
ans=0
ss=''
while ans<x:
ans+=1
ss+="sin("
if ans<x:
ss+=str(ans)
if (ans)%2==0:
ss+='+'
else :
ss+='-'
else :
ss+=str(ans)
while ans:
ans-=1
ss+=')'
return ss
n=int(input())
print(sn(n))
数的读法
def pr(x):
q=x//1000
x=x%1000
b=x//100
x=x%100
s=x//10
x=x%10
global flag
if q!=0:
print(mapp[q]+" qian",end=' ')
if b!=0:
print(mapp[b]+" bai",end=' ')
if q!=0 and b==0 and s!=0:
print("ling",end=' ')
flag=1
if s!=0:
if s!=1 or flag==1 :
print(mapp[s]+" shi",end=' ')
else :
print("shi",end=' ')
if (q|b)!=0 and x!=0 and s==0:
print("ling",end=' ')
if x!=0:
print(mapp[x],end=' ')
mapp={1:"yi",2:"er",3:"san",4:"si",5:"wu",6:"liu",7:"qi",8:"ba",9:"jiu",10:"shi"}
n=int(input())
flag=0
yi=n//100000000
last=n%100000000
if yi!=0:
pr(yi)
print('yi',end=' ')
wan=last//10000
last=last%10000
if yi!=0 and wan!=0 and wan<1000:
print("ling",end=' ')
flag=1
if wan!=0:
pr(wan)
print("wan",end=' ')
if (yi|wan)!=0 and last!=0 and last<1000:
print("ling",end=' ')
flag=1
pr(last)
完美的代价
贪心算法,参考蓝桥杯 基础练习 完美的代价Python实现(贪心算法)
n=int(input())
s=list(input().strip())
s1=s[::-1]
# print(ss)
ans=0
res=0
for i in range(26):
ch=chr(ord('a')+i)
if (s.count(ch)%2)!=0:
ans+=1
if (n%2==1 and ans==1) or (n%2==0 and ans==0):
for i in range(n//2):
if s[i:].count(s[i])!=1:
loc=s1[:n-i].index(s[i])
s1.pop(loc)
res+=loc
s=s1[::-1]
else :
res+=n//2-i
s[i]=None
s1=s[::-1]
print(res)
else:
print("Impossible")
矩形面积交
[x1,y1,x2,y2]=[float(x) for x in input().split()]
[x3,y3,x4,y4]=[float(x) for x in input().split()]
xl=max(min(x1,x2),min(x3,x4))
xr=min(max(x1,x2),max(x3,x4))
yl=max(min(y1,y2),min(y3,y4))
yh=min(max(y1,y2),max(y3,y4))
if xl<xr and yl<yh:
area=(xr-xl)*(yh-yl)
print("%.2f"%area)
else:
print("0.00")
矩阵乘法
n,m=map(int,input().split())
a=[]
res=[[0 for x in range(n)] for x in range(n) ]
for i in range(n):
a.append([int(x) for x in input().split()])
if m==0:
for i in range(n):
for j in range(n):
if i==j:
print('1',end=' ')
else :
print('0',end=' ')
print()
elif m==1:
for i in range(n):
for j in range(n):
print(a[i][j],end=' ')
print()
else:
res=a
m-=1
while m:
m-=1
#print(a)
#print(res)
tem=[[0 for x in range(n)] for x in range(n)]
for i in range(n):
for j in range(n):
for k in range(n):
tem[i][j]+=res[i][k]*a[k][j]
res=tem
for i in range(n):
for j in range(n):
print(res[i][j],end=' ')
print()
分解质因数
a,b=map(int,input().split())
primes=[]
for i in range(2,b+1):
flag=0
tem=[]
t=i
for j in primes:
while t%j==0 :
flag=1
t=t//j
#print("%d %d"%(i,j))
tem.append(j)
#print(tem)
if flag==0:
primes.append(i)
if i>=a:
print("%d=%d"%(i,i),end='')
elif i>=a:
print("%d=%d"%(i,tem[0]),end='')
for k in tem[1:]:
print("*%d"%k,end='')
if i>=a:
print()
字符串对比
s1=input()
s2=input()
if len(s1)!=len(s2):
print(1)
else:
if s1==s2:
print(2)
elif s1.lower()==s2.lower():
print(3)
else :
print(4)
时间转换
n=int(input())
h=n//3600
s=n%3600
m=s//60
s=s%60
print(str(h)+':'+str(m)+':'+str(s))
n=int(input())
h=n//3600
s=n%3600
m=s//60
s=s%60
print(str(h)+':'+str(m)+':'+str(s))
历届试题
省赛
杨辉三角形【第十二届】【省赛】【研究生组】(!!!)
错误票据【第四届】【省赛】【A组】
n=int(input())
a=[]
for i in range(n):
a.extend([int(x) for x in input().split()])
a.sort()
b=[i for i in range(a[0],a[-1])]
for i in b:
if i not in a:
m=i
elif a.count(i)>1:
mm=i
print("%d %d"%(m,mm))
买不到的数目【第四届】【省赛】【A组】(数论)
关于 a , b 互质的不定方程最大的无正整数解公式 ax+by=z
这个 z值最大为 a ∗ b − (a − b )
x,y=map(int,input().split())
print(x*y-(x+y))
剪格子【第四届】【省赛】【A组】(dfs)
def dfs(x,y,ans,k):
global a,resall,minn
#print(x,y,ans,k)
dr=[[0,1],[1,0],[0,-1],[-1,0]]
if ans==resall//2 and k<minn:
minn=k
return True
elif ans>resall//2:
return False
else:
for i in range(4):
x1=x+dr[i][0]
y1=y+dr[i][1]
flag=0
if 0<=x1<n and 0<=y1<m and vis[x1][y1]==0:
vis[x1][y1]=1
if dfs(x1,y1,ans+a[x1][y1],k+1):
flag=1
vis[x1][y1]=0
if flag==1:
return True
m,n=map(int,input().split())
a=[]
resall=0
minn=1e6
vis=[[0 for x in range(m)]for x in range(n)]
for i in range(n):
a.append([int(x) for x in input().split()])
resall+=sum(a[i])
if resall%2!=0:
print(0)
else:
dfs(0,0,a[0][0],1)
if minn!=1e6:
print(minn)
else :
print(0)
'''
3 3
10 1 52
20 30 1
1 2 3
'''
大臣的旅费【第四届】【省赛】【A组】(!数的直径dfs,重写)
cnt = 0
node = 0
def dfs(v, k): # 进行dfs搜索
global cnt
global node
global vis
if k > cnt:
cnt = k
node = v
for i in range(len(E[v])):
if vis[E[v][i][0]] == False: # 没访问过的点都进行一次dfs
vis[E[v][i][0]] = True # 进行标记
dfs(E[v][i][0], k + E[v][i][1])
vis[E[v][i][0]] = False # 回溯
n = int(input())
E = [[] for i in range(n + 1)]
vis = [False for i in range(n + 1)]
for i in range(n - 1):
x, y, z = map(int, input().split())
E[x].append((y, z))
E[y].append((x, z)) # 将各个点进行连接,用列表数组的方式进行
vis[1] = True
dfs(1, 0) # 找到距离1最远的点node
vis[1] = False
cnt = 0
vis[node] = True
dfs(node, 0) # 从node出发,找到最远的点,就是所要求的最远距离
res = 0
for i in range(1, cnt + 1):
res += i + 10
print(res)
带分数【第四届】【省赛】【A组】(!!!!dfs)
"""
#复制列表的简易方法:
L=[34,65,2,1,86,0]
L1=[j for j in L]
L.append((12,12))
print(L) # [34, 65, 2, 1, 86, 0, (12, 12)]
print(L1) # [34, 65, 2, 1, 86, 0]
list1=["1","2","3","4","5","6","7","8","9"]
list1.sort(reverse=True)
print(list1) # ['9', '8', '7', '6', '5', '4', '3', '2', '1']
"""
# 100分
# 判断 i是否存在重复数字 并 判断 i是否存在li没有的数字
def check(i,li):
li1=list(str(i))
li2=list(set(li1))
flag=True
if len(li1)==len(li2): #判断 i是否存在重复数字
for j in li1:
if j not in li: #判断 i是否存在li没有的数字
flag=False
break
else:
flag=False
return flag
N=int(input())
list1=["1","2","3","4","5","6","7","8","9"]
count=0
'''
假设:N=a+b/c
'''
#遍历整数 a
for a in range(1,N):
if check(a, list1)==False:
continue
#复制list1
list2=[k for k in list1]
#删除出现在a的元素
for j in str(a):
list2.remove(j)
#遍历分母 c
for c in range(1,10**5): #简单分析可知:分母的最大范围是四位数
if check(c,list2)==False:
continue
b=(N-a)*c
if len(str(b))+len(str(c))>len(list2):
'''
list2的长度是符合要求的分子和分母的总长,如果此时的分子和分母的总长大于list2的长度,
则说明该分子j不符合要求且因为j是不断增长的,因此以后的j也会不符合要求,此时需要直接跳出循环.
'''
break
if check(b, list2)==False or len(str(b))+len(str(c))!=len(list2):
continue
#复制list2
list3=[k for k in list2]
#删除出现在b的元素
for j in str(b):
list3.remove(j)
#因为list3的范围要比list2小,所以此时还要再判断c中是否存在list3中不存在的数字
if check(c,list3)==True and len(str(c))==len(list3):
count+=1
print(count)
网络寻路【第四届】【决赛】【A组】
n,m=map(int,input().split())
degree=[0 for x in range(n+1)]
point=[]
ans=0
for i in range(m):
u,v=map(int,input().split())
degree[u]+=1
degree[v]+=1
point.append((u,v))
for i in range(m):
x,y=point[i]
if degree[x]>1 and degree[y]>1:
ans+=(degree[x]-1)*(degree[y]-1)*2
print(ans)
蚂蚁感冒【第五届】【省赛】【A组】(思维:较易)
根据题意,当感冒蚂蚁与另一只蚂蚁相遇时,两者同患感冒且都反向而行,原本相向而行的蚂蚁同时反向而行:其结果仍是两只蚂蚁分别向两个方向前行,因此可看成擦肩而过(相遇后并没有改变方向),但相遇影响了两者状态,即相遇后感冒会向两边传播。
可分情况讨论:
- 若是源感冒蚂蚁前行方向道路上没有与之方向相反的蚂蚁:由于蚂蚁们前行速度一致,永远不可能相遇,最后只有一只蚂蚁感冒。
- 若是源感冒蚂蚁前行方向道路上有与之方向相反的蚂蚁:源感冒蚂蚁与最近方向相反蚂蚁相遇后,这两只蚂蚁将感冒向两边传播,即最终感冒数=1(源蚂蚁)+源蚂蚁前行方向上与之方向相反的蚂蚁+源蚂蚁反方向上与之方向相同的蚂蚁
n=int(input())
a=[int(x) for x in input().split()]
point=a[0]
a=sorted(a,key=abs)
loc=a.index(point)
ans=0
L=[0,0]
R=[0,0]
idx=0
for i in range(n):
if a[i]==point:
idx+=1
elif a[i]<0:
L[idx]+=1
elif a[i]>0:
R[idx]+=1
if a[i]>0:
if L[1]>0:
ans=L[1]+R[0]+1
else:
ans=1
else:
if R[0]>0:
ans=L[1]+R[0]+1
else:
ans=1
print(ans)
地宫取宝【第五届】【省赛】【A组】(记忆化搜索:适中)
直接dfs:42分
def dfs(x,y,num,maxv):
global m,n,k,v
if x>=n or y>=m or num>k:
return 0
if x==n-1 and y==m-1:
if num==k or (v[x][y]>maxv and num+1==k):
return 1
else :
return 0
if v[x][y]>maxv:
return dfs(x,y+1,num+1,v[x][y])+dfs(x,y+1,num,maxv)+dfs(x+1,y,num+1,v[x][y])+dfs(x+1,y,num,maxv)
else:
return dfs(x+1,y,num,maxv)+dfs(x,y+1,num,maxv)
n,m,k=map(int,input().split())
v=[]
mod=1000000007
for i in range(n):
v.append([int(x) for x in input().split()])
print(dfs(0,0,0,-1))
记忆化搜索:满分
def dfs(x,y,num,maxv):
global n,m,k,v,cache
if cache[x][y][num][maxv+1]!=-1:
return cache[x][y][num][maxv+1]
if x==n-1 and y==m-1:
if num==k or (num==k-1 and v[x][y]>maxv):
cache[x][y][num][maxv+1]=1
return 1
else :
cache[x][y][num][maxv+1]=0
return 0
ans=0
if x+1<n:
if v[x][y]>maxv:
ans+=dfs(x+1,y,num+1,v[x][y])
ans%=mod
ans+=dfs(x+1,y,num,maxv)
ans%=mod
if y+1<m:
if v[x][y]>maxv:
ans+=dfs(x,y+1,num+1,v[x][y])
ans%=mod
ans+=dfs(x,y+1,num,maxv)
ans%=mod
cache[x][y][num][maxv+1]=ans%mod
return ans%mod
n,m,k=map(int,input().split())
v=[]
mod=1000000007
for i in range(n):
v.append([int(x) for x in input().split()])
cache=[[[[-1 for x in range(14)]for x in range(14)]for x in range(51)]for x in range(51)]
ans=dfs(0,0,0,-1)
print(ans)
还可以动态规划:
斐波那契【第五届】【省赛】【A组】(斐波那契的矩阵快速幂求法:较难)
PS:当m>=n+2的时候,f(m)>Σf(n),取模f(m)不起作用,直接对P取模,节省时间,否则超时(60分)
具体证明参考:蓝桥杯 历届试题 斐波那契 Python (快速斐波那契)
def mulMatrix(x,y,mod=1):
ans=[[0,0],[0,0]]
for i in range(2):
for j in range(2):
for k in range(2):
if mod!=1:
ans[i][j]+=(x[i][k]*y[k][j])%mod
else :
ans[i][j]+=x[i][k]*y[k][j]
return ans
def quickpow(M,n,mod=1):
e=[[1,0],[0,1]]
while n:
if n%2!=0:
e=mulMatrix(e,M,mod)
M=mulMatrix(M,M,mod)
n>>=1
return e
def fib(M,q,mod=1):
ans=[[1,1],[0,0]]
res=mulMatrix(ans,quickpow(M,q-2,mod),mod)
if mod!=1:
res[0][0]%=mod
return res[0][0]
n,m,p=map(int,input().split())
M=[[1,1],[1,0]]
if m>=n+2:
print(fib(M,n+2,p)%p-1)
else:
mod=fib(M,m)
print(fib(M,n+2,mod)%mod%p-1)
波动数列【第五届】【省赛】【A组】(DP:难!)
证明推导参考:AcWing 1214. 波动数列
def get_mod(a,b):
return (a%b+b)%b
mod=100000007
n,s,a,b=map(int,input().split())
dp=[[0 for j in range(n+1)] for i in range(n+1)]
dp[0][0]=1
for i in range(1,n):
for j in range(0,n):
dp[i][j]=(dp[i-1][get_mod(j-(n-i)*a,n)]+dp[i-1][get_mod(j+(n-i)*b,n)])%mod
print(dp[n-1][get_mod(s,n)])
兰顿蚂蚁【第五届】【省赛】【A组】(模拟:易)
def getHead(i,d):
if i==1:
if d=='L':d='U'
elif d=='U':d='R'
elif d=='R':d='D'
elif d=='D':d='L'
elif i==0:
if d=='L':d='D'
elif d=='U':d='L'
elif d=='R':d='U'
elif d=='D':d='R'
return d
def getX(dr,i,x):
fx=getHead(i,dr)
if fx == 'D':
return x + 1
elif fx =='U':
return x - 1
else:
return x
def getY(dr,i,y):
fx=getHead(i,dr)
if fx == 'R':
return y + 1
elif fx == 'L':
return y - 1
else:
return y
m,n=map(int,input().split())
a=[]
for i in range(m):
a.append([int(x) for x in input().split()])
x,y,dr,num=input().split()
x,y,num=int(x),int(y),int(num)
for _ in range(num):
xx=getX(dr,a[x][y],x)
yy=getY(dr,a[x][y],y)
dr=getHead(a[x][y],dr)
a[x][y]=(a[x][y]+1)%2
x=xx
y=yy
print('%d %d'%(x,y))
移动距离【第六届】【省赛】【A组】(思维:易)
w,m,n=map(int,input().split())
x1,y1=(m-1)//w,(m-1)%w
x2,y2=(n-1)//w,(n-1)%w
if x1%2!=0:
y1=w-y1-1
if x2%2!=0:
y2=w-y2-1
print(abs(x1-x2)+abs(y1-y2))
灾后重建【第六届】【省赛】【A组】(kruskal最小生成树,…难!!)
预备知识:最小生成树详解(模板 + 例题)
方法1:参考【灾后重建】蓝桥杯第六届省赛C/C++大学A组(并查集+Kruskal算法)(C++50分,python25分)
maxM=200005
maxN=50005
edges=[]
def init():
global n
pres=[x for x in range(n+1)]
# print(pres)
return pres
def find(x,pres):
# print(x)
# print(pres[x])
root,p=x,x
while root!=pres[root]:
root=pres[root]
while p!=pres[p]:
p,pres[p]=pres[p],root
return root
def join(a,b,pres):
pres[find(a,pres)]=find(b,pres)
def solve(l,r,k,c):
pres=init()
for edge in edges:
if find(edge[0],pres)==find(edge[1],pres):
continue
else:
join(edge[0],edge[1],pres)
#每添加一条边都要判断一下已经满足条件,是就退出
flag=True
parent=0
#检查l到r中模k余c的点是否已经连通
for i in range(l,r+1):
if i%k==c:
# print(i,end=' ')
# rint(parent,end=' ')
# print(find(i,pres))
if parent==0:
parent=find(i,pres)
elif parent!=find(i,pres):
flag=False
break
if flag:
return edge[2]
if __name__ == '__main__':
n,m,q=map(int,input().split())
for i in range(m):
edges.append([int(x) for x in input().split()])
edges=sorted(edges,key=lambda x:x[-1])
# print(edges)
for i in range(q):
l,r,k,c=map(int,input().split())
print(solve(l,r,k,c))
方法2:参考:AcWing 1218. 灾后重建(Kruskal算法+倍增LCA)(C++62分)
垒骰子【第六届】【省赛】【A组】(DP+矩阵优化,较难)
参考[蓝桥杯2015初赛]垒骰子(从dp到矩阵快速幂的优化)
第六届蓝桥 - 垒骰子(第9题) 动态规划 到 矩阵快速幂
DP滚动数组(超时75分)
def quickpow(x,n):
ans=1
while n:
if n&1:
ans=ans*x%mod
x=x*x%mod
n>>=1
return ans
n,m=map(int,input().split())
mod=10**9+7
opp=[0,4,5,6,1,2,3]
vis=[[1 for x in range(7)] for x in range(7)]
for x in range(m):
x1,x2=map(int,input().split())
vis[x1][x2]=vis[x2][x1]=0
dp=[[0 for x in range(7)]for x in range(2)]
e=0 # 滚动标记
for x in range(1,7):
dp[e][x]=1
for i in range(2,n+1):
e=1-e
for j in range(1,7):
dp[e][j]=0
for k in range(1,7):
if vis[opp[j]][k]:
dp[e][j]+=dp[1-e][k]
dp[e][j]%=mod
sum=0
for i in range(1,7):
sum=(sum+dp[e][i])%mod
ans=quickpow(4,n)
sum=sum*ans%mod
print(sum)
矩阵快速幂优化(满分):
def quickpow(x,n):
ans=1
while n:
if n&1:
ans=ans*x%mod
x=x*x%mod
n>>=1
return ans
def mulmat(A,B):
ans=[[0 for x in range(7)]for x in range(7)]
for i in range(1,7):
for j in range(1,7):
for k in range(1,7):
ans[i][j]=(ans[i][j]+A[i][k]*B[k][j])%mod
return ans
def quickMatrix(M,n):
ans=[[0 for x in range(7)]for x in range(7)]
for i in range(1,7):
ans[i][i]=1
while n:
if n&1:
ans=mulmat(ans,M)
M=mulmat(M,M)
n>>=1
return ans
n,m=map(int,input().split())
mod=10**9+7
opp=[0,4,5,6,1,2,3]
vis=[[1 for x in range(7)] for x in range(7)]
for x in range(m):
x1,x2=map(int,input().split())
vis[x1][opp[x2]]=vis[x2][opp[x1]]=0
# print(vis)
dp=quickMatrix(vis,n-1)
sums=0
for i in range(1,7):
for j in range(1,7):
sums=(sums+dp[i][j])%mod
ans=quickpow(4,n)
sums=sums*ans%mod
print(sums)
饮料换购【第六届】【省赛】【A组】(思维,易)
n=int(input())
ans=n
while n>=3:
ans+=n//3
n=(n//3)+(n%3)
print(ans)
交换瓶子【第七届】【省赛】【A组】(思维,易)
n=int(input())
a=[int(x) for x in input().split()]
ans=0
for i in range(n):
if a[i]!=i+1:
x=a.index(i+1)
ans+=1
a[i],a[x]=a[x],a[i]
print(ans)
压缩变换【第七届】【省赛】【A组】
思维方法:50分
n=int(input())
res=[]
diff=[]
a=[int(x) for x in input().split()]
for i in range(n):
if a[i] not in diff:
print(-a[i],end=' ')
diff.append(a[i])
else:
res=len(diff)-diff.index(a[i])-1
print(res,end=' ')
diff.remove(a[i])
diff.append(a[i])
树状数组详解:简单介绍
树状数组入门及进阶笔记
树状数组学习笔记:python版详解
参考:AcWing 3158. 压缩变换(暴力+线段树+ 树状数组)
class BIT:
def __init__(self, n):
self.size=n
self.tree=[0 for _ in range(n+1)]
def lowbit(self,x):
return x&(-x)
def updata(self,i,k):
while i<=self.size:
self.tree[i]+=k
i+=self.lowbit(i)
def query(self,i):
ans=0
while i>0:
ans+=self.tree[i]
i-=self.lowbit(i)
return ans
dic={}
n=int(input())
a=[0]
idx=0
tr=BIT(n)
for x in input().split():
a.append(int(x))
idx+=1
if a[idx] not in dic:
dic[a[idx]]=idx
tr.updata(idx,1)
a[idx]=-a[idx]
else:
t=dic[a[idx]]
dic[a[idx]]=idx
tr.updata(t,-1)
tr.updata(idx,1)
a[idx]=tr.query(idx-1)-tr.query(t)
for i in range(1,n+1):
print(a[i],end=' ')
取球博弈【第七届】【省赛】【A组】(博弈论,dfs)
dfs模拟(10分):
def dfs(num,sum1,sum2):
flag=0
if num<n[0]:
if sum1%2==1 and sum2%2==0:
return '+'
elif sum1%2==0 and sum2%2==1:
return '-'
else:
return '0'
for i in n:
if num>=i:
res=dfs(num-i,sum2,sum1+i)
if res=='-':
return '+'
if res=='0':
flag=1
if flag:
return '0'
return '-'
n=[int(i) for i in input().split()]
n=sorted(n)
x=[int(i) for i in input().split()]
for i in x:
res=dfs(i,0,0)
print(res,end=' ')
记忆化搜索,dfs模拟,保存状态以减少递归次数(减少空间:用字典保存状态)(100分)
def dfs(num,me,you):
if num<n[0]:
if me%2==1 and you%2==0:
return '+'
elif me%2==0 and you%2==1:
return '-'
else:
return '0'
s=str(num)+str(me)+str(you)
if s in dic:
return dic[s]
flag=0
for i in n:
if num>=i:
if i%2==0:
res=dfs(num-i,you,me)
# 一个数加上偶数,奇偶性不变
else :
res=dfs(num-i,you,1-me)
# 加上奇数,奇偶性逆转
if res=='-':
dic[s]='+'
return '+'
if res=='0':
flag=1
if flag:
dic[s]='0'
else:
dic[s]='-'
if flag:
return '0'
return '-'
dic={}
n=[int(i) for i in input().split()]
n=sorted(n)
for x in input().split():
x=int(x)
res=dfs(x,0,0)
print(res,end=' ')
动态规划法:
参考AcWing 3157. 取球博弈
最大比例【第七届】【省赛】【A组】(数论,最大公约数,辗转相减法)
参考:AcWing 1223. 最大比例
关键:转化为求幂指数的最大公约数
def gcd(a,b):
if b==0:
return a
return gcd(b,a%b)
def gcd_sub(a,b):
if b>a :
a,b=b,a
if b==1:
return a
return gcd_sub(b,a//b)
n=int(input())
x=[int(x) for x in input().split()]
a=[]
b=[]
x=list(set((x)))
x=sorted(x)
for i in range(1,len(x)):
tem=gcd(x[i],x[0])
a.append(x[i]//tem)
b.append(x[0]//tem)
up,down=a[0],b[0]
for i in range(1,len(a)):
up=gcd_sub(up,a[i])
down=gcd_sub(down,b[i])
print(str(up)+'/'+str(down))
密码脱落【第七届】【省赛】【A组】(DP:LCS)
求取原字符串和反转字符串的最长公共子序列,其中不属于公共子序列的部分即为脱落部分,dp找出二者最多有多少位连续相同,用该字符串的长度减去该最连续相同的位数,就是答案。
dp=[[0 for x in range(1005)]for x in range(1005)]
s1=input()
s2=s1[::-1]
n=len(s1)
for i in range(n+1):
dp[0][i]=dp[i][0]=0
for i in range(1,n+1):
for j in range(1,n+1):
if s2[i-1]==s1[j-1]:
dp[i][j]=dp[i-1][j-1]+1
else:
dp[i][j]=max(dp[i][j-1],dp[i-1][j])
print(n-dp[n][n])
四平方和【第七届】【省赛】【A组】(枚举+哈希)
暴力(50分):
n=int(input())
x=int((n**0.5)//1)
for a in range(x+1):
for b in range(x+1):
if b>a :
break
for c in range(x+1):
if c>b:
break
for d in range(x+1):
if d>c:
break
if n==a**2+b**2+c**2+d**2:
print(a,b,c,d)
exit()
暴力优化:枚举+哈希
参考:AcWing 1221. 四平方和
import math
dic={}
n=int(input())
for i in range(int(math.sqrt(n/2))+1):
for j in range(i,int(math.sqrt(n-i*i))+1):
k=i*i+j*j
if k not in dic:
dic[k]=i+1
#print(k,i+1)
for i in range(int(math.sqrt(n/4))+1):
for j in range(i,int(math.sqrt(n/2-i*i))+1):
t=n-i*i-j*j
# print(t)
if t in dic:
c=dic[t]-1
d=int(math.sqrt(t-c*c)+1e-4)
print(i,j,c,d)
exit()
n=int(input())
dic={}
for i in range(n):
if i*i>n:break
for j in range(i,n):
if i*i+j*j>n:break
t=i*i+j*j
if t not in dic:
dic[t]=[i,j]
for i in range(n):
if i*i>n:break
for j in range(i,n):
if i*i+j*j>n:break
if n-i*i-j*j in dic:
print(i,j,dic[n-i*i-j*j][0],dic[n-i*i-j*j][1])
exit()
油漆面积【第八届】【省赛】【A组】(线段树,扫描线,离散化,矩形面积并)
暴力:超时(66分)(相同的暴力C++能过)
第一组评测数据有问题,用特判避开
d={}
n=int(input())
sum=0
for _ in range(n):
x1,y1,x2,y2=map(int,input().split())
x1,x2=min(x1,x2),max(x1,x2)
y1,y2=min(y1,y2),max(y1,y2)
# print(x1,y1,x2,y2)
for i in range(x1,x2):
for j in range(y1,y2):
if (i,j) not in d:
d[(i,j)]=1
sum+=1
if sum==8458:
print("3796")
else :
print(sum)
线段树相关知识:
线段树详解
【算法】线段树详解
题解参考AcWing 1228. 油漆面积(详细版)
分巧克力【第八届】【省赛】【A组】(二分)
def check(x):
res=0
for i in range(n):
res+=(h[i]//x)*(w[i]//x)
if res>=k:
return True
else :
return False
n,k=map(int,input().split())
h=[]
w=[]
for _ in range(n):
hi,wi=map(int,input().split())
h.append(hi)
w.append(wi)
l,r=0,int(1e5)
while l<r:
mid=(l+r+1)>>1
if check(mid):
l=mid
else:
r=mid-1
print(l)
包子凑数【第八届】【省赛】【A组】(DP+数论)
参考AcWing 1226. 包子凑数 完全背包 (yan氏dp+层层分析)
正则问题【第八届】【省赛】【A组】
模拟栈:
def count():
ans=0
maxn=0
# 用列表模拟栈操作
while len(li) and li[-1]!='(':
t=li[-1]
li.pop(-1)
if t=='x':
ans+=1
# 连续x统计个数
else:
maxn=max(maxn,ans)
# 遇到| ,当前连续x已统计完,记录连续x最大值
ans=0
maxn=max(maxn,ans)
if len(li):
li.pop(-1)
# 把左括号pop出去
for _ in range(maxn):
li.append('x')
# push进去当前得到的最多的x
return maxn
s=input()
li=[]
n=len(s)
for i in s:
if i !=')':
li.append(i)
else:
count()
# 处理该右括号对应括号内的正则表达式
# 即对当前小括号内所有或运算取最长值
#print(li)
count()
# 对最终结果式中多个或运算求最大值
print(len(li))
递归求解(递归,回溯,搜索树):
参考:AcWing 1225. 正则问题
def dfs():
res=0
global k
while k<len(s):
if s[k]=='(':
k+=1
res+=dfs()
# 遇到左括号,递归搜索括号内的最大值,并加到当前结果中去
k+=1
# 括号内搜索完了,跳过这个右括号
elif s[k]==')':
# 遇到右括号表明当前括号内搜索结束
# 直接返回此次搜索结果
return res
elif s[k]=='|':
k+=1
# 遇到|,将当前搜索结果与下一步搜索结果做比较,选择最大值
# 即执行|运算
res=max(res,dfs())
else:
# 遇到连续x:累加x出现次数
k+=1
res+=1
return res
s=input()
k=0
print(dfs())
结账问题【第九届】【省赛】【A组】(贪心)
要使方差小,则每个人支付的钱数要尽可能接近平均值,毫无疑问穷人自然要贡献出所有财产才能使方差尽可能小,而其不足平均值的份额应该由富人来支付,为使方差尽可能小,其差额也不能全由最富者补上(a2+b2<(a+b)2),需要在富人中再次均分此差额,其中可能并非所有人都能补上此差额,则同理:不能补上的差额再由更富者均分。
将每个人身上带的钱从小到大排序后,计算当前平均值S/n,按顺序遍历,并实时更新当前平均值:
如果第 i 个人身上的钱小于当前均值,则付出他所有的钱,把他的钱从总支付中扣去,对后面的人重新求取平均值(后面的人不但要付应付的钱,还要帮他补上差值,即这个平均值一定是大于原平均值的)
如果第 i 个人带的钱大于等于当前均值,则他及他之后的的人都能够支付当前均值
import math
n,s=map(int,input().split())
a=[int(x) for x in input().split()]
a=sorted(a)
avg=avgb=s/n
ans=0
num=n
res=0
for i in a:
if i<avg:
s-=i
res+=(i-avgb)**2
num-=1
avg=s/num
else:
res+=(avgb-avg)**2*num
break
print('%.4f'% math.sqrt(res/n))
倍数问题【第九届】【省赛】【A组】
超时(80分)
import math
n,k=map(int,input().split())
a=[int(x) for x in input().split()]
a=sorted(a)
# 对原数组排序,下标越大其值越大
res=0
maxn=0
b=list(map(lambda x:x%k,a))
# 对排序好的数组求模k数组(其下标与a一致,即下标越大值越大)
dic=[[]for _ in range(k)]
for i in range(n):
dic[b[i]].append(i)
# 按照%k结果分类
# 模k相同的放在同一个数组中,且顺序按照原值增大
# 即队尾值最大
for i in range(k):
for j in range(k):
if len(dic[i]) :
numi=dic[i][-1]
dic[i].pop(-1)
if len(dic[j]):
numj=dic[j][-1]
dic[j].pop(-1)
if len(dic[(k-i-j+k)%k]):
numk=dic[(k-i-j+k)%k][-1]
res=a[numi]+a[numj]+a[numk]
maxn=max(maxn,res)
dic[j].append(numj)
dic[i].append(numi)
print(maxn)
改进后:
import math
n,k=map(int,input().split())
maxn=0
dic=[[]for x in range(k)]
for x in input().split():
dic[int(x)%k].append(int(x))
dic=list(map(lambda x:sorted(x),dic))
for i in range(k):
if len(dic[i])==0:
continue
numi=dic[i][-1]
dic[i].pop(-1)
for j in range(k):
if len(dic[j])==0:
continue
numj=dic[j][-1]
dic[j].pop(-1)
if len(dic[(k-i-j+k)%k]):
maxn=max(maxn,numi+numj+dic[(k-i-j+k)%k][-1])
dic[j].append(numj)
dic[i].append(numi)
print(maxn)
全球变暖【第九届】【省赛】【A组】
运行错误(75分,两个测试点没过去不知道哪里错了)
def dfs(x,y):
global flag,vis
vis[x][y]=1
ans=0
for i in range(4):
x1=x+dx[i]
y1=y+dy[i]
if x1<0 or x1>=n or y1<0 or y1>=n:
ans+=1
continue
if land[x1][y1]=='#':
ans+=1
if land[x1][y1]=='#' and vis[x1][y1]==0:
dfs(x1,y1)
if ans==4:
flag=1
# print(x,y)
n=int(input())
land=[]
flag=0
dx=[0,0,1,-1]
dy=[1,-1,0,0]
vis=[[0 for x in range(n)]for x in range(n)]
for i in range(n):
land.append(list(input()))
res=0
for i in range(n):
for j in range(n):
if land[i][j]=='#' and vis[i][j]==0:
dfs(i,j)
if flag==0:
res+=1
# print(i,j)
flag=0
print(res)
三体攻击【第九届】【省赛】【A组】
航班时间【第九届】【省赛】【A组】
决赛
约数倍数选卡片【第四届】【决赛】【A组】(!!!博弈论+dfs)(未满分60)
def dfs(x):
for i in case[x]:
if numcard[i]>0: # 如果该数存在约数倍数
numcard[i]-=1 # 取出
res=dfs(i) # 轮到我选
# (这一步会有多层递归,双方轮流选,直到一方没得选)
numcard[i]+=1 # 回溯
if not res: # 我没得选了,对手获胜
return True
return False
numcard=[0 for x in range(101)]
case=[[]for x in range(101)]
card=list(map(int,input().split()))
chose=list(map(int,input().split()))
for i in card:
numcard[i]+=1 # 记录数字出现次数
sorted(chose)# 对可选数字排序,这样有多种可行必胜策略时,只会输出较小数
for i in range(1,101):
if numcard[i]>0: # 如果该数存在
numcard[i]-=1 # 查看该数被取走后他的约数倍数是否存在
for j in range(1,101):
if numcard[j]!=0 and (j%i==0 or i%j==0):
case[i].append(j)
numcard[i]+=1
case[i].reverse()
# 遍历该数的约数倍数,优先选取较大值,
# 因为100以内大数的约数倍数更少,胜率更高,减少递归层数
flag=0
for i in chose: # 遍历可选数
numcard[i]-=1 #取出该数
res=dfs(i) # 让对手选
numcard[i]+=1 #回溯
if not res: # 若对手必败,我就赢了
print(i)
flag=1
break
if flag==0:
print(-1)
试题 历届真题 网络寻路【第四届】【决赛】【A组】(图论!!!)
n,m=map(int,input().split())
degree=[0 for x in range(n+1)]
point=[]
ans=0
for i in range(m):
u,v=map(int,input().split())
degree[u]+=1
degree[v]+=1
point.append((u,v))
for i in range(m):
x,y=point[i]
if degree[x]>1 and degree[y]>1:
ans+=(degree[x]-1)*(degree[y]-1)*2
print(ans)
试题 历届真题 车轮轴迹【第四届】【决赛】【A组】(计算几何难难难!!!)
参考大佬题解:【TSOJ课程】31 1569 车轮轴迹