计蒜客2020 蓝桥杯大学 A 组模拟赛(三)Python题解

受限于版权,不再复制题面。题目可以通过购买计蒜客蓝桥杯2020课程,或者单独复现比赛获取。这里仅仅提供我的Python解答和代码。

总体来说比第一次模拟赛题目难度有下降,有参考性。

A.抛硬币

不用说了,独立事件,答案是0.50

B.求零点

经典的二分求解。当然你如果真的有耐心也可以暴力枚举(雾)。答案1.849016

def f(x):
    return x**5-15*x**4+85*x**3-225*x**2+274*x-121

L=1.5
R=2.4
while L+1E-10<R:
    M=(L+R)/2
    if f(M)>0:
        L=M
    else:
        R=M

print("%.6f"%L)

C.棋盘放置

似乎有点像需要dfs搜索的问题。但是这个手动枚举更方便。很容易知道答案不会超过总对角线数15。同时可以构造出一种放置14个的方案(最左边一列放8个,最右边一列放6个),容易看出,不可能比14更加优了。

当然如果有多余时间,也可以用代码验证。

D.突破障碍

不错的一道题。属于迷宫类型,但是又有所不同。题目中要求S到T穿梭过的最小障碍物个数。考虑总的代价stp[i][j],代表到达某个格子经过的障碍数(包括自身)。由于每走过一格stp[i][j]不一定增长1,因此单纯四方向扩展,队列不一定会非递减。似乎不能用广搜bfs直接求解。这里我们需要稍微改造广搜,不是简单地把相邻格子放入队列,而是将相邻格子所有连通的未访问的.格子都更新好stp,并且放入队列。这是因为这些格点的stp值已经确定和新格子一致,不会再出现有更小的答案了。这么做的话,队列中的状态在扩展过程中stp就都是非递减的而且差值不过1。每一步更新的正确性有所保证。

实现中采用了一个expand函数来扩展相邻.格子,包含一个广搜。因此总体上有点嵌套的感觉。

答案为6。如果时间紧张,可以先蒙上一个答案。

from queue import Queue

dx=(0,1,0,-1)
dy=(1,0,-1,0)

n=m=15
s=[]
for i in range(n):
    s.append(input())
    if s[i].__contains__("S"):
        sta=(i,s[i].index("S"))
    if s[i].__contains__("T"):
        ed=(i,s[i].index("T"))
        
Q=Queue()
stp=[[-1]*m for i in range(n)]

def expand(x,Orig_Q):
    Q=Queue()
    Q.put(x)
    Orig_Q.put(x)
    while not Q.empty():
        u=Q.get()
        for j in range(4):
            v=(u[0]+dx[j],u[1]+dy[j])
            if 0<=v[0]<n and 0<=v[1]<m and s[v[0]][v[1]]!='#' and stp[v[0]][v[1]]==-1:
                stp[v[0]][v[1]]=stp[u[0]][u[1]]
                Q.put(v)
                Orig_Q.put(v)
                

stp[sta[0]][sta[1]]=0
expand(sta,Q)
while not Q.empty():
    u=Q.get()
    for j in range(4):
        v=(u[0]+dx[j],u[1]+dy[j])
        if 0<=v[0]<n and 0<=v[1]<m and stp[v[0]][v[1]]==-1:
            stp[v[0]][v[1]]=stp[u[0]][u[1]]+1
            expand(v,Q)
            
print(stp[ed[0]][ed[1]])

E.歌手

可以通过dfs搜索来求解,也可以通过枚举全排列来求解。因为只有9个数字,所以直接用permutations生成器来做。

答案为:99360

(注意permutations和C++中的next_permutation还是有所不同的,前者是不管你有重复数字的,[1,2,3,3]会被枚举两遍)

from itertools import permutations

a=[1,1,1,2,3,3,4,4,5]
cnt=0

for i in permutations(a):
    f=True
    for j in range(len(i)-1):
        if i[j]==i[j+1]:
            f=False;
    if f:
        cnt+=1
print(cnt)

F.Chess

注意到想要安全,那么必须要避开所有的attack的情况,因此我们暴力枚举,并且不用管中间有没有越子,因为如果越子,肯定已经不安全了,不影响答案。

n=int(input())
s=[]
for i in range(n):
    t=input().split()
    t[1]=int(t[1])
    t[2]=int(t[2])
    s.append(t)

def ATK(a,b):
    if a[0]=='B':
        return b[1]-b[2]==a[1]-a[2] or b[2]+b[1]==a[1]+a[2]
    if a[0]=='R':
        return a[1]==b[1] or a[2]==b[2]
    return b[1]-b[2]==a[1]-a[2] or b[2]+b[1]==a[1]+a[2] or a[1]==b[1] or a[2]==b[2]

for i in range(n):
    for j in range(n):
        if i!=j and ATK(s[i],s[j]):
            print("Attack!")
            exit(0)
print("Safe!")

G.掷骰子

简单的动态规划问题,暴力+打表可以拿部分分。

dp[i][j]代表前面i次,投的总和为j的方案总数。递推式子也很简单,枚举本次扔了那个点数。因为是长度为6的滑动窗口,所以可以省掉内部的6次循环(当然不省去正式比赛肯定也可以过)。

n,s=map(int,input().split())

dp=[[0]*(s+1) for i in range(n+1)]
mo=998244353

dp[0][0]=1
for i in range(1,n+1):
    tmp=0
    for j in range(s+1):
        dp[i][j]=tmp%mo
        if j>=6:
            tmp-=dp[i-1][j-6]
        tmp+=dp[i-1][j]
print(dp[n][s])

H.旅行

暴力dfs路径计数可水分。

“只有编号较小的城市能走向编号较大的城市”这句话很重要,说明了这个图是一个DAG(有向无环图)。我们可以定义dp[i]表示到第i个点的方案数。这里更新的顺序,我们只需要从1..n自然循环即可,因为到dp[i]的时候,所有连到i的点dp必然已经确定了。

(当然你也可以用拓扑排序算法做这题,稍微麻烦咯)

n,m=map(int,input().split())
E=[[] for i in range(n+1)]
mo=998244353

for i in range(m):
    a,b=map(int,input().split())
    if a>b:
        a,b=b,a
    E[a].append(b)

ans=[0]*(n+1)
ans[1]=1
for i in range(n+1):
    ans[i]%=mo
    for j in E[i]:
        ans[j]+=ans[i]
print(ans[n])

I.养猫

这里如果你手动模拟一下,发现其实是一个反向的“合并果子”问题。

合并果子是经典问题。根据贪心,或者“哈弗曼编码的思路”,每次取头最小的两个果子合并即可。

from queue import Queue
n=int(input())

a=sorted(list(map(int,input().split())))

class Queue:
    def __init__(self):
        self.d=[0]*n
        self.hd=self.tl=0

    def get(self):
        self.hd+=1
        return self.d[self.hd-1]

    def put(self,x):
        self.d[self.tl]=x
        self.tl+=1

    def empty(self):
        return self.hd==self.tl

    def front(self):
        return self.d[self.hd]

Q1=Queue()
Q2=Queue()

for i in a:
    Q1.put(i)

ans=0
for i in range(1,n):
    if not Q1.empty() and (Q2.empty() or Q1.front()<Q2.front()):
        u=Q1.get()
    else:
        u=Q2.get()
    if not Q1.empty() and (Q2.empty() or Q1.front()<Q2.front()):
        v=Q1.get()
    else:
        v=Q2.get()
    Q2.put(u+v)
    ans+=u+v

print(ans)

这里手工实现了队列。正常比赛其实没太大必要。

J.小明的赈灾计划

求一个子区间,使得其中异或和最大。首先根据前缀和思想,我们把问题转化为一堆数中,取两个数字,异或值最大。这里可以O(n^2)水分。

正解的话这里暂时不作介绍,使用了一种叫做Trie的数据结构,将每个数字插入Trie中,再在Trie中二进制贪心。

class Trie:
    def __init__(self,n):
        self.ch=[None,[0,0]]
        self.sz=1

    def insert(self,x):
        u=1
        for i in range(31,-1,-1):
            c=x>>i&1
            if not self.ch[u][c]:
                self.sz+=1
                self.ch[u][c]=self.sz
                self.ch.append([0,0])
            u=self.ch[u][c]

    def query(self,x):
        u=1
        ans=0
        for i in range(31,-1,-1):
            c=x>>i&1^1
            if self.ch[u][c]:
                u=self.ch[u][c]
                ans|=1<<i
            else:
                u=self.ch[u][c^1]
        return ans

n=int(input())
a=[0]+list(map(int,input().split()))
T=Trie(n)
T.insert(0)
for i in range(1,n+1):
    a[i]^=a[i-1]
    T.insert(a[i])

ans=0
for i in range(n+1):
    ans=max(ans,T.query(a[i]))
print(ans)     
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,525评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,203评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,862评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,728评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,743评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,590评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,330评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,244评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,693评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,885评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,001评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,723评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,343评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,919评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,042评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,191评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,955评论 2 355

推荐阅读更多精彩内容

  • 31.33% 1000ms 131072K 请对于下面式子进行填空,填入加减乘,使这个表达式成立。1空 2 空 3...
    myleosu阅读 356评论 0 0
  • 一、 购物单小明刚刚找到工作,老板人很好,只是老板夫人很爱购物。老板忙的时候经常让小明帮忙到商场代为购物。小明很厌...
    _弓长_大人阅读 763评论 0 0
  • 【问题描述】乐羊羊饮料厂正在举办一次促销优惠活动。乐羊羊C型饮料,凭3个瓶盖可以再换一瓶C型饮料,并且可以一直循环...
    QuietBlade阅读 858评论 0 0
  • 最重要的事情只有一件,目前有基础的是写作,说练口才,还有练习备考雅思。 可是我还要工作,备课…… 不想把那么多精力...
    稚童千阳阅读 163评论 0 0
  • 难得来西子一次,我和阿宝一起去游戏大厅玩。 吃完牛排。我们又决定在西子玩一会。我们去了星奇乐。那里可是...
    JIN宇康阅读 56评论 0 0