USACO 2022 February Contest, Gold Problem 2. Cow Camp
To qualify for cow camp, Bessie needs to earn a good score on the last problem of the USACOW Open contest. This problem has TT distinct test cases (2≤T≤1032≤T≤103) weighted equally, with the first test case being the sample case. Her final score will equal the number of test cases that her last submission passes.
Unfortunately, Bessie is way too tired to think about the problem, but since the answer to each test case is either "yes" or "no," she has a plan! Precisely, she decides to repeatedly submit the following nondeterministic solution:
if input == sample_input: print sample_output else: print "yes" or "no" each with probability 1/2, independently for each test case
Note that for all test cases besides the sample, this program may produce a different output when resubmitted, so the number of test cases that it passes will vary.
Bessie knows that she cannot submit more than KK (1≤K≤1091≤K≤109) times in total because then she will certainly be disqualified. What is the maximum possible expected value of Bessie's final score, assuming that she follows the optimal strategy?
The only line of input contains two space-separated integers TT and K.K.
The answer as a decimal that differs by at most 10−610−6 absolute or relative error from the actual answer.
2 3
1.875
In this example, Bessie should keep resubmitting until she has reached 33 submissions or she receives full credit. Bessie will receive full credit with probability 7878 and half credit with probability 1818, so the expected value of Bessie's final score under this strategy is 78⋅2+18⋅1=158=1.87578⋅2+18⋅1=158=1.875. As we see from this formula, the expected value of Bessie's score can be calculated by taking the sum over xx of p(x)⋅xp(x)⋅x, where p(x)p(x) is the probability of receiving a score of xx.
4 2
2.8750000000000000000
Here, Bessie should only submit twice if she passes fewer than 33 test cases on her first try.
Problem credits: Benjamin Qi
[/hide]
(Analysis by Benjamin Qi)
Let's ignore the sample case by subtracting one from TT (at the end, we'll add one back to the answer). Then the probability of Bessie's solution solving exactly ii test cases out of TT is precisely pi=(Ti)2T.pi=(Ti)2T.
Define ExEx to be the expected value given at most xx submissions, where E0=0E0=0. The goal is to compute EKEK. If we have already computed ExEx then Ex+1Ex+1 may be computed as follows:
In equations,
Subtask 1: The above equations can be simulated in O(TK)O(TK) time.
The solution below uses Python's decimal module for increased precision (though it was not necessary to do so).
from decimal import * getcontext().prec = 100 T, K = map(int, input().split()) T -= 1 prob = [Decimal(1)] for _ in range(T): prob = [(x+y)/2 for x, y in zip([Decimal(0)]+prob, prob+[Decimal(0)])] E = Decimal(T)/2 K -= 1 while K > 0: K -= 1 next_E = 0 for i in range(T+1): next_E += prob[i]*max(i,E) E = next_E getcontext().prec = 20 print(E+1)
Subtask 2: Let a=∑⌊Ex⌋i=0pia=∑i=0⌊Ex⌋pi and b=∑Ti=⌊Ex⌋+1ipi,b=∑i=⌊Ex⌋+1Tipi, such that Ex+1=aEx+b.Ex+1=aEx+b. Observe that when ⌊Ex+1⌋=⌊Ex⌋⌊Ex+1⌋=⌊Ex⌋, we do not need to recalculate aa and bb.
The runtime of the solution below is O(T2+K)O(T2+K).
T, K = map(int, input().split()) T -= 1 prob = [1] for _ in range(T): prob = [(x+y)/2 for x, y in zip([0]+prob, prob+[0])] E = T/2 K -= 1 for f in range(T): a, b = 0, 0 for i in range(T+1): if i <= f: a += prob[i] else: b += prob[i]*i while K > 0 and E < f+1: E = a*E+b K -= 1 print(E+1)
Full Credit: For a solution without a factor of O(K)O(K), we need to be able to advance xx multiple submissions forward at once.
Under this assumption, we can write
by the geometric series formula. It remains to either determine that ⌊EK⌋=⌊Ex⌋⌊EK⌋=⌊Ex⌋, or find the smallest q≤K−xq≤K−x such that ⌊Ex+q⌋>⌊Ex⌋.⌊Ex+q⌋>⌊Ex⌋.
After finding qq via one of the two methods below, we may simulate min(q,K−x)min(q,K−x) submissions at once and then update x+=min(q,K−x)x+=min(q,K−x). If we now have x=Kx=K, then we're done. Otherwise, we know that ⌊Ex⌋⌊Ex⌋ has increased by one. ⌊Ex⌋⌊Ex⌋ can increase a total of at most TT times, which is a lot smaller than KK.
Method 1: Binary search on qq.
My code follows. The total number of calls to powpow is O(TlogK)O(TlogK).
from decimal import * getcontext().prec = 100 T, K = map(int, input().split()) T -= 1 prob = [Decimal(1)] for _ in range(T): prob = [(x+y)/2 for x, y in zip([Decimal(0)]+prob, prob+[Decimal(0)])] E = Decimal(T)/2 K -= 1 for f in range(T): if K == 0: break if E // 1 > f: continue a, b = Decimal(0), Decimal(0) for i in range(T+1): if i <= f: a += prob[i] else: b += prob[i]*i def next_E(q): # value of E after q timesteps return pow(a,q)*E+(1-pow(a,q))/(1-a)*b # binary search on q q_lo = 1 while 2*q_lo <= K and next_E(q_lo*2) < f+1: q_lo *= 2 q_hi = 2*q_lo while q_lo < q_hi: q_mid = (q_lo+q_hi)//2 if next_E(q_mid) < f+1: q_lo = q_mid+1 else: q_hi = q_mid # advance q submissions q_lo = min(q_lo, K) K -= q_lo E = next_E(q_lo) getcontext().prec = 20 print(E+1)
Method 2: We can rewrite ⌊Ex+q⌋>⌊Ex⌋⌊Ex+q⌋>⌊Ex⌋ as follows:
Then we can take the natural logarithm of both sides to get
The runtime of the solution below is O(T2)O(T2). aa corresponds to probabilityLowerprobabilityLower and b1−ab1−a corresponds to expectedHigherexpectedHigher.
Danny Mittal's code:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.StringTokenizer; public class CowCamp { public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer tokenizer = new StringTokenizer(in.readLine()); int t = Integer.parseInt(tokenizer.nextToken()) - 1; int k = Integer.parseInt(tokenizer.nextToken()); double[][] probability = new double[t + 1][t + 1]; probability[0][0] = 1.0; for (int a = 1; a <= t; a++) { probability[a][0] = probability[a - 1][0] / 2.0; for (int b = 1; b <= t; b++) { probability[a][b] = (probability[a - 1][b - 1] + probability[a - 1][b]) / 2.0; } } double expected = .0; int attempts = 0; for (int score = 1; score <= t; score++) { double probabilityLower = .0; for (int lower = 0; lower < score; lower++) { probabilityLower += probability[t][lower]; } double expectedHigher = .0; for (int higher = score; higher <= t; higher++) { expectedHigher += probability[t][higher] * ((double) higher); } expectedHigher /= 1.0 - probabilityLower; double difference = expectedHigher - expected; double differenceToAchieve = expectedHigher - ((double) score); double attemptsNeeded = Math.log(differenceToAchieve / difference) / Math.log(probabilityLower); boolean doneHere = attemptsNeeded > k - attempts; int attemptsToUse = doneHere ? (k - attempts) : (int) Math.round(Math.ceil(attemptsNeeded)); difference *= Math.pow(probabilityLower, attemptsToUse); expected = expectedHigher - difference; attempts += attemptsToUse; if (attempts == k) { break; } } System.out.println(1.0 + expected); } }
[/hide]
翰林课程体验,退费流程快速投诉邮箱: yuxi@linstitute.net 沪ICP备2023009024号-1