博主0408的時候參加了微衆筆試,感覺題目不難但是沒有全AC。下來複盤的時候感覺自己考試的時候可能是腦子進水了,很多顯而易見的情況都沒考慮到。果然這段時間沉迷小說遊戲綜藝讓腦子也變得安逸了。閒話不再續,下面正式覆盤。
1 分禮物
有n位小朋友去小明家裏拜年,小明準備了m份禮物。小明想把所有禮物平均分給每個小朋友,每個小朋友得到相同個數的禮物。但是m未必能被n整除,小明可以使用以下兩種操作任意多次(兩種操作可以同時使用)。
1、 給其中一個小朋友發紅包,收到紅包的小朋友會離開小明家。每個紅包需要花費a元。
2、 購買一個新禮物,每個禮物價值爲b元。
問小明最少花費多少元,才能使得所有禮物可以被剩下的小朋友平分。
第一行輸入四個整數n,m,a,b(1≤n,m,a,b≤100)。
輸出最少花費。
輸入樣例1
7 5 10 100
20
輸入樣例2
2 2 10 10
輸出樣例2
0
輸入樣例3
3 1 10 10
輸出樣例3
20
樣例解釋
樣例一發兩個紅包。樣例二不需要任何操作。樣例三買兩個新禮物,或者發兩個紅包,或者發一個紅包買一個新禮物。
由於被測試用例糊住了,先入爲主的認爲送禮物的數量等於送走的朋友數,實際上這種等式關係只有m<n或其他特定情況才成立。也是沾了測試用例的光,這種想法居然也A了91。
此題的point恰恰在於送禮物的數量不一定等於送走的朋友數,假設送走了個小朋友,買了個新禮物,題目要求,且最小。可以遍歷做。
def test(n,m,a,b):
min = None
if m%n == 0:
return 0
else:
# 假設紅包送走i個小朋友
for i in range(n):
# 剩下n-i個小朋友中沒有禮物的小朋友
if n==i:
res = n*a
else:
if m%(n-i)==0:
res = i*a
else:
tmp = (n-i) - m%(n-i)
res = tmp * b + i*a
if not min or min>res:
min = res
return min
2 迴文遊戲
Cassidy和Eleanore是一對好朋友,她們經常會一起玩遊戲。某一天她們玩了一個迴文遊戲。遊戲規則是這樣的:給出一個僅包含小寫字母的字符串S,在每一個人的回合中,她們會進行兩個操作:
1 嘗試重新排列這個字符串,如果可以把這個字符串排列成迴文字符串,則立即獲勝。
2 否則,她們必須刪掉字符串中的一個字符。
已知,Cassidy先手,在兩個人都採取最佳策略的情況下,誰可以獲勝。
輸入第一行僅包含一個正整數t,表示數據組數,(t<=10)
接下來有t行,每行有一個字符串S,表示一組測試數據。(|S|<=1000)
對於每組數據輸出一行,如果Cassidy獲勝,則輸出Cassidy,否則輸出Eleanore
輸入樣例
2
aba
ab
輸出樣例
Cassidy
Eleanore
這個題還是比較友好,全ac了。一個字符串若能構成迴文串,串中計數爲奇數的字符個數不能大於1,否則無法構成字符串。最優策略就是,先檢查字符串,若能構成迴文串,勝利;若不能,優先將串中計數爲偶數的字符刪掉一個。
def createDic(s):
dic = {}
for i in s:
if i not in dic:
dic[i] = 1
else:
dic[i] += 1
return dic
def testPalin(dic):
odd_count = 0
even_count = 0
for key in dic:
if dic[key] % 2 == 1:
odd_count += 1
else:
even_count += 1
if odd_count > 1:
return False
else:
return True
def delString(dic):
# 如果存在偶數,將偶數刪成奇數,使奇數儘可能多
flag = False
for key in dic:
if dic[key] > 0 and dic[key]%2 == 0:
dic[key] -= 1
flag = True
break
# 如果刪除失敗,沒有偶數字符;只能刪除奇數字符
if not flag:
for key in dic:
if dic[key] > 0 and dic[key] % 2 == 1:
dic[key] -= 1
break
def test(s):
# s:字符串
dic = createDic(s)
count = 0
while True:
if testPalin(dic):
if count%2==0:
return 'Cassidy'
else:
return 'Eleanore'
else:
delString(dic)
count += 1
3 抽卡遊戲
抽卡是一類類似於博弈的遊戲。現在有一種抽卡方式,描述如下:
初始你只有一次抽卡機會。每次抽卡浪費一次抽卡機會,獲得一張卡片。這張卡片上有兩個數字,第一個數字代表你能獲得的錢,第二個數字代表你能獲得的額外抽卡次數。額外的抽卡次數是可以累計的。
現在,你知道了卡片的數量,所有的卡片上的數字,以及所有卡片的順序。你只需要安排一種抽卡順序,使得你能獲得錢數最多。
輸入:
第一個行一個數n,代表卡片的數量。 接下來n行,每行用兩個數ai,bi描述一張卡片。ai表示抽這張卡能獲得的錢數,bi表示抽這張卡能獲得的額外抽卡次數。
輸出:
一行一個數,代表你能獲得的最多錢數。
輸入樣例
5
0 2
1 1
1 0
1 0
2 0
輸出樣例
4
對於100%的數據,0≤a_i,b_i≤1000,1≤n≤1000。樣例解釋:按順序抽第2,1,5,4張卡
此題我的想法是先把有抽卡次數的卡抽了,再按照錢數大小抽卡。看了牛客大家的思路都是類似的,但是我只ac了72。仔細比照了一下代碼,實在是發現不出來問題。
不過:其實可以先把有抽卡次數的全部先消耗掉(即有抽卡次數的卡不參與排序),只排序無抽卡次數,有錢數的卡。
後來發現可能不是邏輯的問題,而是while循環的判斷有誤,可能還有count值但是卡已經抽完了,這個時候我的代碼會報邊界錯誤。果然筆試時不能再主文件寫try…except,否則有錯誤也不會報出來。
def test(arr):
arr = sorted(arr,key=lambda x:(x[1],x[0]),reverse=True)
# arr = sorted(arr, key=lambda x: (-x[0], x[1]))
print(arr)
count = 1
money = 0
for i in range(len(arr)):
if count == 0: break
tmp =arr[i]
count = count - 1 + tmp[1]
money = money + tmp[0]
return money