Editorial for CCC '22 S4 - Good Triplets
Submitting an official solution before solving the problem yourself is a bannable offence.
Author:
For the first subtask, it suffices to follow the definition of a good triplet. Firstly, there are  ways
to select 
. Secondly, consider the condition that the origin is strictly inside the triangle. This is
equivalent to saying that 
, 
, and 
 divide the circle into 
 arcs, and each arc is strictly shorter than 
.
This leads to the following approach. Sort the positions so that 
, then check that
For example, the first of these checks can be implemented in code as P[b]-P[a] < (C+1)/2 in C++ or
Java, or P[b]-P[a] < (C+1)//2 in Python 3.
For the second subtask, the goal is to find a solution that works well when  is small. Let 
 be the
number of points drawn at location 
. If three locations 
 satisfy the second condition, we want to add
 to the answer. This approach is 
 and is too slow. However, we can improve from
three nested loops to two nested loops. If 
 and 
 are chosen already, either 
 does not exist, or 
 is in an
interval. It is possible to replace the third loop with a prefix sum array. This algorithm's time complexity is 
.
It is possible to optimize this approach to  and earn 
 marks. The idea is to eliminate both the 
and 
 loop. Start at 
 and compute 
 in 
 time. The next step is to transition from 
 to
, and to maintain 
 in 
 time. This requires strong familiarity with prefix sum arrays. Care
with overflow and off-by-one errors is required.
Comments
I found this problem a lot easier to think about if you count triplets of points that don't form a triangle and subtract that from the total number of triplets. These are exactly the triplets whose points all belong on a closed half of the circle, so sweeping two pointers along the circle suffices to do this in
 time.