前言:除特殊说明外题解均可AC
- [蓝桥杯2016初赛]网友年龄
- [蓝桥杯2016初赛]生日蜡烛
- [蓝桥杯2016初赛]方格填数
- [蓝桥杯2016初赛]寒假作业
- [蓝桥杯2016初赛]剪邮票
- [蓝桥杯2016初赛]四平方和
- [蓝桥杯2016初赛]密码脱落
- [蓝桥杯2016初赛]最大比例
- [蓝桥杯2016初赛]煤球数目
- [蓝桥杯2016初赛]凑算式
- [蓝桥杯2016初赛]交换瓶子
- [蓝桥杯2016初赛]报纸页数
- [蓝桥杯2016初赛]平方怪圈
- [蓝桥杯2016初赛]冰雹数
- [蓝桥杯2016初赛]卡片换位
- [蓝桥杯2016初赛]搭积木
- [蓝桥杯2016初赛]取球博弈
- [蓝桥杯2016初赛]压缩变换
- [蓝桥杯2016初赛]有奖猜谜
思路:枚举网友的年龄情况,符合条件的就计数
cnt = 0
for age in range(10, 100):
sonage = int(str(age)[-1::-1])
if age - sonage == 27:
cnt += 1
#print(age, sonage)
print(cnt)
[蓝桥杯2016初赛]生日蜡烛
思路:除了要知道开始过生日的年龄,还要知道现在多少岁,枚举开始过生日和现在年龄,直接计算出一共吹了多少蜡烛,符合条件则输出即可。
for start in range(0, 100):
for end in range(start, 100):
tot = (start+end)*(end-start+1)//2
if tot == 236:
print(start)
[蓝桥杯2016初赛]方格填数
思路:直接爆搜就行,dfs枚举所有的情况,符合情况的计数就行。
N = 10
a = [[-2 for i in range(N)] for j in range(N)]
vis = [False for i in range(N)]#vis[i]表示数字i的使用情况
a[1][1] = -1#左上角
a[3][4] = -1#右下角
cnt = 0
def check(x, y, num):
dx = [-1, 0, 1]#x的偏移
dy = [-1, 0, 1]#y的偏移
for i in dx:
for j in dy:
#X,Y表示相邻的位置
X = x+i
Y = y+j
if X > 3 or X < 1 or Y < 1 or Y > 4:#越界
continue
if (X == 1 and Y == 1) or (X == 3 and Y == 4):#左下角和右下角
continue
if a[X][Y] == -1 or a[X][Y] == -2:#未填入数字的位置
continue
if X == x and Y == y:#正在被填入数字的位置
continue
if abs(a[X][Y] - num) == 1:#相邻位置的数字连续
return False
return True
def dfs(x, y):
#X, Y是要填数字的格子
Y = y + 1
if Y > 4:
Y = 1
X = x+1#换行
else:
X = x
if a[X][Y] == -1:#抵达右下角
global cnt
cnt += 1
return
for i in range(10):#枚举0-9
if (not vis[i]) and check(X, Y, i):#i没有被使用过并且i是合法的
vis[i] = True
a[X][Y] = i
dfs(X, Y)
a[X][Y] = -2
vis[i] = False
dfs(1, 1)
print(cnt)
[蓝桥杯2016初赛]寒假作业
思路:枚举每个方块的数字,然后直接判断是否合法,合法就计数。
值得一提的是,等式右边的数不需要枚举,可以通过等式左边的数计算的出。
N = 10
a = [[-1 for i in range(N)] for j in range(N)]
vis = [False for i in range(20)]
cnt = 0
def dfs(x, y):
if x == 4 and y == 3:#填好了最后一个方块
global cnt
cnt+=1
newx = x
newy = y#newx, newy表示需要填的方块位置
newy += 1
if newy > 3:
newx += 1
newy = 1
if newy == 3:#如果需要填的方块在等式的右边
if x == 1:
num = a[x][1]+a[x][2]#直接计算出结果即可
if num < 1 or num > 13:#超出范围
return
if vis[num]:#已经被使用过了
return
a[newx][newy] = num
elif x == 2:
num = a[x][1]-a[x][2]
if num < 1 or num > 13:
return
if vis[num]:
return
a[newx][newy] = num
elif x == 3:
num = a[x][1]*a[x][2]
if num < 1 or num > 13:
return
if vis[num]:
return
a[newx][newy] = num
else:
num = a[x][1]//a[x][2]
if num*a[x][2] != a[x][1]:#可以被除尽
return
if num < 1 or num > 13:
return
if vis[num]:
return
a[newx][newy] = num
vis[num] = True
dfs(newx, newy)
vis[num] = False
else:
for i in range(1, 14):
if vis[i]:
continue
a[newx][newy] = i
vis[i] = True
dfs(newx, newy)
vis[i] = False
dfs(1, 0)
print(cnt)
[蓝桥杯2016初赛]剪邮票
思路:每一张邮票有两种状态,剪或者不剪。
于是我们可以枚举每个邮票的状态,然后在最后进行判断,是不是所有剪的邮票都是连接在一起的,如果是则记录。
import copy
a= [[0 for i in range(10)] for j in range(10)]#0表示没有被剪,1表示剪了
ans = 0
dx = [1, -1, 0, 0]
dy = [0, 0, 1, -1]
def check():
#判断是否是只有一个连通块
cnt = 0#连通块数量
b = copy.deepcopy(a)
for i in range(3):
for j in range(4):
if b[i][j] == 1:
dfs1(i, j, b)
cnt+=1
return cnt == 1
def dfs1(x, y, b):
b[x][y] = 0
for i in range(4):
X = x + dx[i]
Y = y + dy[i]
if X < 0 or X > 2 or Y < 0 or Y > 3:#超出范围
continue
if b[X][Y] == 1:
dfs1(X, Y, b)
def dfs(num, cnt):
if cnt == 5:#已经剪了五张邮票
if check():#并且满足五张邮票连接在一起
global ans
ans += 1
return
if num == 12:#已经判断完最后一个位置的状态
return
x = num//4#num对应的x坐标
y = num%4#num对应的坐标
for i in range(2):#每个位置有选和不选两种状态
if i == 0:#不选
dfs(num+1, cnt)
else :#选
a[x][y] = 1
dfs(num+1, cnt+1)
a[x][y] = 0
#从左到右,从上到下一次枚举每个位置的邮票能不能
dfs(0, 0)
print(ans)
[蓝桥杯2016初赛]四平方和
思路:如果使用暴力四层循环肯定会超时的,四层循环可以优化成三层循环,但是还是超时(c++不会超时就很……),于是想办法可不可以优化成两层循环。
仔细观察四平方的式子,左边是一对平方和,右边也是一对平方和,又考虑到N的范围不大,于是乎我们是不是可以直接预处理出所有平方和,然后我们只需要枚举a和b,通过查表直接得到c和d。
那么枚举a和b就是两层for循环了。
from math import sqrt
N = 5000010
ne = [-1 for i in range(N)]#查询表
#预处理出所有的平方和
for c in range(N):
if c*c > N:#超出范围不考虑
break
for d in range(c, N):
k = c*c + d*d
if k > N:#超出范围不考虑
break
if ne[k] == -1:
ne[k] = c#有两个数的平方和为k,且较小的数为c
while True:
try:
n = int(input())
flag = 0
for a in range(n+1):
if a*a > n:
break
for b in range(a, n+1):
k = a*a + b*b
if k > n:
break
if ne[n-k] != -1:
c = ne[n-k]#查表得出c
d = int(sqrt(n-k-c*c))#算出d
print(a, b, c, d)
flag = 1
if flag:
break
if flag:
break
except:
break
[蓝桥杯2016初赛]密码脱落
前言:这题超时了,想不明白
思路:假定给我们的字符串是s1,那么我们如果可以求出s中的最长对称的子串s2(不要求连续),那么s1中除去字串的字符就是造成s不能对称的原因,那我们把这些字符继续在s1中补充,则不就得到了原字符串。
然后原字符串的长度减去s1的长度,应该也会等于s1的长度减去s2的长度。
那我们最终要求的就是s1中的最长对称子串的长度。
求s1的最长对称子串的长度,其实是等于s1与其反向字符串的最小公共子序列长度。
def lcs(s1, s2):
f = [[0 for i in range(1010)] for j in range(1010)]
for i in range(len(s1)):
for j in range(len(s2)):
if s1[i] == s2[j]:
f[i+1][j+1] = f[i][j]+1
else:
f[i+1][j+1] = max(f[i+1][j], f[i][j+1])
return f[len(s1)][len(s2)]
while True:
s1 = input()
s2 = s1[::-1]#反转字符串
l = lcs(s1, s2)
print(len(s1) - l)
[蓝桥杯2016初赛]最大比例
[蓝桥杯2016初赛]煤球数目
思路:直接找规律就很容易发现,设f[i]为第i层的数目,则有f[i]-f[i-1] = i。
tot = 0
st = 1
d = 2
for i in range(100):
tot += st
st += d
d += 1
print(tot)
[蓝桥杯2016初赛]凑算式
思路:因为每个字母的数字不同,也就是将1到9的全排列分配下去。
如果不懂库函数里的内置函数可以自己直接暴力for循环。
import itertools
ls = [i for i in range(1, 10)]
cnt = 0
for num in itertools.permutations(ls):
a,b,c,d,e,f,g,h,i = num
DEF = d*100 + e*10 + f
GHI = g*100 + h*10 + i
tot = a + (b*GHI + c*DEF)/(c*GHI)
if int(tot) == tot and tot == 10:
cnt+=1
print(cnt)
[蓝桥杯2016初赛]交换瓶子
思路:观察每个位置的瓶子是否合法,如果不合法,则找到合法瓶子的位置,进行交换。
while True:
n = int(input())
a = list(map(int, input().split()))
ne = [-1 for i in range(10010)]#ne[i]表示在a中值为i的下标
cnt = 0
for i in range(len(a)):
ne[a[i]] = i
for i in range(len(a)):
if a[i] != i+1:
temp = a[i]
posi = ne[i+1]
a[i], a[ne[i+1]] = a[ne[i+1]], a[i]
ne[temp] = ne[i+1]
ne[i+1]= i
cnt+=1
print(cnt)
[蓝桥杯2016初赛]报纸页数
思路:这题的难点在于看懂题目意思。
如果按照中间的折痕把这些书叠放在一起,那就成了三张纸,共有12页的报纸了。
题目意思理解了,然后根据对称性,很容易得到答案了。
print(1728 + 1125 - 1)#2852
[蓝桥杯2016初赛]平方怪圈
思路:随便找几个数,只要不是落入1的就可以,然后打印过程看看,找一下最大数直接输出就好了。
##x = 8
##while True:
## strx = str(x)
## tot = 0
## for i in strx:
## tot += int(i)**2
## x = tot
## print(tot)
print(145)
[蓝桥杯2016初赛]冰雹数
思路:证明放下面,想看思路。
首先我们只需要考虑n以内所有的奇数,偶数不需要考虑。
然后如果在变换的过程中碰到了我们已经算过的数可以直接跳过。
通过这两个优化基本就可以AC了。
证明:我们只需要证明偶数的变化过程中的最大值小于1到n中奇数变化过程中的最大值就行。
设a是1到n内的任意一个偶数,则在变化过程中a一直除2直到为一个奇数,a变化过程中的最大值有两种情况,只要这两种情况都小于等于1到n中某个奇数在雪花滚动的就行了。
a的最大值可能是它本身,也有可能是上面所说奇数的最大值。
奇数的最大值已经计算得出。
a-1为一个奇数,且a-1的第一次变化为3(a-1)就已经大于a了。
while True:
n = int(input())
ans = n#不大于n的最大高度
for i in range(3, n+1, 2):
t = i
while t >= i:
t = 3*t+1
ans = max(ans, t)
while not (t&1):
t //= 2
print(ans)
[蓝桥杯2016初赛]卡片换位
思路:确定初始状态和目标状态,从初始状态不断地移动空白块进行状态转移,直到到达目标状态。
这其实也就是一个bfs过程。
dx = [0, 0, -1, 1]
dy = [1, -1, 0, 0]
def bfs():
d = {}
d[now] = 0
q = []
q.append(now)
while len(q):
t = q[0]
q.pop(0)
if t.find('B') == Aindex and t.find('A') == Bindex:#交换了位置
print(d[t])
break
idx = t.find(' ')
#将一位坐标映射到二位位置上
x = idx//3
y = idx%3
for i in range(4):
X = x + dx[i]
Y = y + dy[i]
if X < 0 or X > 1 or Y < 0 or Y > 2:#超出范围
continue
sidx = X*3 + Y
#将空白块进行移动,也就是交换字符串的两个字符
if idx < sidx:
newstr = t[0 : idx] + t[sidx] + t[idx + 1: sidx] + t[idx] + t[sidx+1 : ]
else:
newstr = t[0 : sidx] + t[idx] + t[sidx + 1: idx] + t[sidx] + t[idx+1 : ]
if not (newstr in d):
d[newstr] = d[t] + 1
q.append(newstr)
while True:
a = input()
b = input()
now = a+b
Aindex = now.find('A')
Bindex = now.find('B')
#print(Aindex, Bindex)
bfs()
[蓝桥杯2016初赛]搭积木
思路:爆搜就行了,发现蓝桥真的很喜欢考爆搜。
a = [[-1 for i in range(10)] for i in range(10)]
vis = [False for i in range(10)]#判断数字的使用情况
def dfs(x, y):
if x == 4 and y == 4:#搭完了最后一个积木
global cnt
cnt += 1
y += 1
if y > x:
y = 1
x += 1
for i in range(10):
if vis[i]:#数字已经使用过
continue
#不满足上面的积木大于下面两个的积木
if x-1 > 0 and y -1 > 0 and y-1 <= x-1 and i < a[x-1][y-1]:
continue
if x-1 > 0 and y > 0 and a[x-1][y] > i:
continue
a[x][y] = i
vis[i] = True
dfs(x, y)
vis[i] = False
cnt = 0
dfs(1, 0)#自上而下,自左而右的进行搭积木
print(cnt)
[蓝桥杯2016初赛]取球博弈
[蓝桥杯2016初赛]压缩变换
[蓝桥杯2016初赛]有奖猜谜
思路:局数不多,其实直接用手算也行。
这里给出代码的算法
result = "vxvxvxvxvxvxvvx"
now = 777#剩余数
for i in result:
if i == 'v':#赢了
now <<= 1
else :#输了
now = 0 if now <= 555 else now-555
print(now)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)