codefroces中的病毒,這題有很深的trick,你能解開嗎?


大家好,歡迎閱讀周末codeforces專題。

我們今天選擇的問題是contest 1419的C題,目前有接近8000的人通過了本題。今天這題的難度不大,但是真的很考驗思維,一不小心就會踩中陷阱,我個人覺得非常有意思,適合周末動動腦。

題目鏈接:https://codeforces.com/contest/1419/problem/C

題意

有一個叫做Killjoy的特工發明了一種新型的冠狀病毒叫做Convid-2069,專門在codeforces平台上傳播。這種病毒通過rating傳播,只要兩個人的rating一樣並且其中一個感染了病毒,那么另外一個也會被感染

這個病毒一開始的時候只有Killjoy自己感染了,他一共和n個人有聯系。由於codeforces會定期舉辦比賽,參加比賽會改變一個人的rating,由於codeforces的規則,導致所有參賽的人的rating變動的總量為0,也就是說有人升了一定會有人降,大家的總和保持不變。已知Killjoy自己不會參賽,請問最少需要多少次比賽可以將所有人都感染。

對於每一次比賽,可以不必所有人都參與,傳染的發生不需要時間,瞬間就可以傳染。很容易證明,我們一定可以在有限次比賽當中將所有人都感染。

樣例

首先輸入一個t表示測試數據的組數(),對於每一組數據第一行輸入兩個數,分別是n和x。n表示和Killjoy有接觸的人的數量,x表示Killjoy自己的rating,()。

第二行輸入n個整數,表示這n個人的rating。要求輸出一個整數,表示最少需要的比賽數量()。

題解

這道題的思路非常直接,沒什么彎彎繞,我們只需要觀察一下樣例就可以了。樣例當中有三組數據剛好對應了三種情況。

我們先來看第一種情況:這n個人的rating都和x相等,那么意味着我們不需要比賽,就可以把所有人都感染了。結果當然是0,這一種非常簡單,大家應該都可以想明白。

第二種情況也不難,第二種情況就是雖然大家的rating不全等於x,但是大家的總和等於x * n。也就是說rating大於x的減小到x,小於x的增加到x,剛好可以通過一次比賽讓大家全部被感染,那么最終的答案就是1。這對應樣例當中的68, 70的情況,x=69,很明顯68的增加1,70的減去1,就可以都變成69。

前面兩種理清楚了,再來看第三種情況,第三種情況也就是前面兩種都不符合的情況。也就是我們通過一次比賽沒辦法讓大家都等於x,不過這並沒有什么關系,因為題目當中並沒有限制rating的范圍。我們完全可以讓其中n-1個人全部變成x,由於要保證大家的rating變動之和等於0,所以讓最后一個人來完成平衡的角色。

也就是說通過一次比賽,我們可以讓n-1個人全部被感染,最后留下一個人。那么不難想出,我們只需要再多用一個回合就可以了。再多一個回合,我們可以讓第n個人變成x,讓一個已經感染的人來完成平衡。那么,我們用了兩個回合就完成了所有人的感染。

整理一下思路,其實這題分為三種情況,第一種情況是大家全部都等於x,答案是0。第二種情況是大家可以只需要一個回合就變成x,如果上面兩種情況都不滿足的話,就額外再消耗一個回合即可。

這個思路也太簡單了,很快我就寫好了代碼:

import math
 t = int(input())  for _ in range(t):  n, x = list(map(int, input().split(' ')))  arr = list(map(int, input().split(' ')))   diff = 0  sdiff = 0  for i in range(n):  diff += abs(arr[i] - x)  sdiff += arr[i] - x   # 如果所有人都等於x,那么會在一開始就被感染完  if diff == 0:  print(0)  # 如果可以通過一個回合讓所有人的rating調整到x,那么只需要一個回合  elif sdiff == 0:  print(1)  else:  print(2) 

但是很遺憾,當我提交了之后,並沒有AC,而是錯在了第二組數據。我想了很久,才終於想到了其中的trick。我先不說,大家先思考一下,看看能不能想到。

准備好了嗎?

我們剛才列舉的三種情況是沒有問題的,但是我們遺漏了一種。就是這一開始的n個人當中,可能有人的rating就等於x,所以他會在第一次比賽之前就感染。我們再想想最后一種情況,我們先把n-1個人的rating調整到x,再把調整當中付出的代價交給其中一個人來承擔。這也是我們需要第二個回合的原因,如果這n個人當中存在有人在開始之前就感染了,那么我們完全可以讓這個已經感染的人來承擔代價,這樣我們就可以減少一個回合。

體現在代碼當中,就是我們需要額外增加一個判斷條件,判斷一下這n個人當中是否存在有人的rating等於x,會在一開始的時候就被感染。如果有的話,答案就是1。

附上代碼:

import math
 t = int(input())  for _ in range(t):  n, x = list(map(int, input().split(' ')))  arr = list(map(int, input().split(' ')))   diff = 0  sdiff = 0  flag = False  for i in range(n):  if arr[i] == x:  flag = True  diff += abs(arr[i] - x)  sdiff += arr[i] - x   if diff == 0:  print(0)  # 如果存在人感染,也只需要一個回合就可以完成感染  elif sdiff == 0 or flag:  print(1)  else:  print(2)  

這道題其實並不難,但是很容易漏掉這種情況,這也是codeforces當中題目的魅力所在,考驗我們思維的縝密與細致程度。我個人覺得還是非常有趣的,值得一做。

今天的文章就到這里,衷心祝願大家每天都有所收獲。如果還喜歡今天的內容的話,請來一個三連支持吧~(點贊、關注、轉發

原文鏈接,求個關注

本文使用 mdnice 排版

- END -


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM