-
Weird Algorithm - Follow the instructions and simulate the algorithm.
-
Missing Number - Missing number is
N * (N + 1) / 2 -sum of all numbers given. -
Repetitions - Use for loop and counter to count the longest sequence of equal characters.
-
Increasing Array - Sum of differences greater than
0between adjacent elements including updates. -
Permutations - Print even numbers first and then odd numbers. Edge cases of
N < 4. -
Number Spiral - Diagonal of Nth square is
N * N - N + 1, move up or down from the diagonal. -
Two Knights - Total ways is
N * N * (N * N - 1) / 2. ConsiderN - 1byN - 1board, each knight attacks4squares except knights on edge attack2, so we subtract4 * (N - 1) * (N - 2)from total ways. -
Two Sets - If
N % 4 == 1orN % 4 == 2then no solution, otherwise split numbers by groups of4which can be split into two sets. IfN % 4 == 3then one group will have1 2and the other3. -
Bit Strings - Number of bit strings is
2^N, useMODto avoid overflow. -
Trailing Zeros - Trailing zeros are created by
2 * 5, latter is less frequent, so count number of5factors. Done by summingN / 5^ifori = 1, 2, .... -
Coin Piles - Requirements are that larger pile isn't more than twice as large as smaller because
2/1ratio is max and total coins is divisible by3because we can only remove3coins at a time. -
Palindrome Reorder - Atmost one character can have odd count, put that character in the middle and then put the rest of the characters on both sides in pairs.
-
Gray Code - Solution of
Nis two copies of solution ofN - 1with0and1prepended to each respectively and the latter reversed. -
Tower of Hanoi - Numbers of moves is
2^N - 1, print the moves recursively using the fact thatNdisks can be moved to the third peg by movingN - 1disks to the second peg, moving the last disk to the third peg and then moving theN - 1disks to the third peg. -
Creating Strings I - Use
next_permutationon sorted string to generate all permutations in order. -
Apple Division - Use bitmask to generate all possible subsets of apples and calculate minimum difference. Can also be done recursively.
-
Chessboard and Queens - Iterate across rows, and check if queen can be placed in each columns using arrays to keep track of used columns and diagonals. Backtrack if queen can't be placed.
-
Digit Queries - Can calculate number of digits from
1toNusing fact that there are9 * 10^(i - 1) * idigits from10^(i - 1)to10^i - 1fori = 1, 2, .... Then use binary search to find the number that contains theKth digit. -
Grid Paths - Use backtracking to generate all possible paths and count the ones that reach the bottom left corner. Use optimizations that if reach bottom left corner before
48moves then fail, if more than48moves then fail, if out of bounds then fail, and finally if front and back blocked, but left and right open then fail.
-
Distinct Numbers - Insert numbers into a set and then print the size of the set.
-
Apartments - Sort both apartments and applicants, then assign applicants to smallest apartment that they will accept.
-
Ferris Wheel - Sort children by weight, then use two pointers to assign heaviest child with lightest child that they will accept, if no child will accept then assign heaviest child alone.
-
Concert Tickets - Use multiset to store ticket prices, then assign each customer the ticket with the larger price that they will accept.
-
Restaurant Customers - Iterate through all given start and end times in order, increment counter for start times and decrement counter for end times, keep track of maximum counter value.
-
Movie Festival - Sort movies by end time, then greedily choose the movies if they start after the previous movie ends.
-
Sum of Two Values - Sort numbers, then use two pointers to find the pair that sums to
X. -
Maximum Subarray Sum - Use Kadane's algorithm to find the maximum subarray sum.
curr = max(curr + x, x)andans = max(ans, curr). -
Stick Lengths - Optimal length is the median of the lengths, so sort the lengths and then calculate the median.
-
Missing Coin Sum - Sort coins, start with being able to create all numbers from
0toX = 0. If next coinCis greater thanX + 1then we can't createX + 1, otherwise we can createX + 1by using the next coin and now we can create all numbers from0toX + Cby induction. -
Collecting Numbers - Iterate through numbers in order, if position of number is less than position of previous number then increment counter. Use map to store position of each number.
-
Collecting Numbers II - Use previous solution to calculate initial counter, then deal with
V[a]andV[b]along with their neighbors and update counter accordingly. Use set to not count duplicates. -
Playlist - Use map to store last position of each song, then iterate through songs and update counter with the max difference between current position and last position of song.
-
Towers - Directly simulate the process using multiset and add box to smallest tower that it will fit in, if no tower will fit then create new tower.
-
Traffic Lights - Use multiset to store traffic light positions and differences. When a new light is added find light before and after it, remove the difference between them from the multiset and add the difference between the new light and the two lights to the multiset.
-
Josephus Problem I - Use ordered set to efficiently store and remove people. Use a pointer to keep track of the current person and increment it by
2and mod by size each time. -
Josephus Problem II - Use ordered set to efficiently store and remove people. Use a pointer to keep track of the current person and increment it by
Kand mod by size each time. -
Nested Ranges Check - Sort ranges in order by start time primarily, and in reverse order by end time secondarily. Iterate from first to last keeping track of maximum end time, if current end time is less than maximum end time then the current range is nested inside a previous range. Iterate from last to first keeping track of minimum end time, if current end time is greater than minimum end time then a previous range is nested inside current range.
-
Nested Ranges Count - Same logic as previous problem, except use ordered set to keep track of end times and use
order_of_keyto find number of end times less than/greater than current end time. -
Room Allocation - Use a min heap priority queue to store an array of end time, counter, and index. Insert rooms by index into priority queue, if the top room ends before the current customer then remove it and insert the current customer into the room, else create a new room for the current customer by incrementing the counter. Once all customers are processed, print the counter and the room number for each customer using the index.
-
Factory Machines - Given a time
T, it's possible to calculate the number of products that can be produced by iterating through all machines and addingT / V[i]to the total. Use binary search to find the minimum timeTsuch that the total number of products is greater than or equal toN. -
Tasks And Deadlines - It is optimal to do the tasks in order of duration from shortest to longest, consider arbitrary short task A, and long task B, and the two orders possible. Furthermore, for the same duration, it is optimal to do the tasks in order of deadline from earliest to latest, pretty self explanatory. Sort the tasks in this order and then iterate through them to calculate the total cost.
-
Reading Books - And optimal method is to have person A read the longest book, and the person B read the smaller books in the meantime. Once the longest book is read, Person A just reads the books in order of decreasing length, person B can follow just behind person A. This leads to a total time of either sum of all books, or twice the longest book.
-
Sum Of Three Values -
O(N^2)is allowed, so iterate through all numbers once, and then two pointers on the remaining suffix to find the pair that sums toX - V[i]. This triple satisfies as a solution, if they are unique. -
Sum Of Four Values - Store all sums of pairs, along with their original indices. use two pointers on the pairs to find the pair that sums to
Xand that the indices are unique. Iterate once focusing on moving left pointer forward, and once focusing on moving right pointer backward in case of non-unique indices. This is to handle edge cases. -
Nearest Smaller Values - Use a stack to store the previous numbers, and pop off the stack until the top of the stack is smaller than the current number. If the stack is empty, then the nearest smaller value is
0. Otherwise, the nearest smaller value is the top of the stack. -
Subarray Sums I - Iterate across array, keeping track of current prefix sum, and storing the frequency of all previous prefix sums in a map. If the current prefix sum minus
Xis in the map, then add the frequency to the answer. -
Subarray Sums II - Previous solution had no dependence on positive numbers, so same exact code works for this problem.
-
Subarray Divisibility - Similar to previous two problems, except use a map to store the frequency of all previous prefix sums modulo
N. -
Subarray Distinct Values - Use a two pointers method of iterating through the array, storing frequencies of numbers in a map. If the number of distinct numbers is less than or equal to
K, then increment the right pointer, else increment the left pointer until the number of distinct numbers is less than or equal toK. At each valid iteration, add the size of the subarray to the answer. -
Array Division - Given a maximum subarray sum, it's possible to calculate the number of subarrays necessary in
O(N)by iterating through the array. Use binary search to find the minimum subarray sum that has a number of subarrays is less than or equal toK. -
Sliding Median - Use an ordered set to efficiently query for the median using
find_by_order. Using a sliding window over the array to add and remove elements from the ordered set. -
Sliding Cost - Use two multisets to represents the window above the median and the window less than or equal to the median. Also keep track of the sum of these multisets. Figure out adding and removing logistics for each multiset. To answer each window for the lower multiset subtract sum of lower multiset from median times size of lower multiset, and add sum of upper multiset minus median times size of upper multiset.
-
Movie Festival II - Similar to the previous version, except this time use a multiset to store the end times of the movies currently being watched by the
Kpeople, and replace the person with the latest end time before the current potential movie with the current potential movie. -
Maximum Subarray Sum II - Calculate all prefix sums, and then iterate through the indices of the array. Store the prefix sums of the indices between
AandBless than the current index in a multiset. Update the answer by subtracting the minimum prefix sum from the current prefix sum, this is the maximum subarray sum ending at the current index. Checking all indices leads to the maximum subarray sum of the entire array.
-
Dice Combinations - The state
DP[i]will represent the number of ways to get a sum ofiusing the dice. The initial state isDP[0] = 1representing one way to get a sum of0, and the transition isDP[i] = sum(DP[i - q])for1 <= q <= 6, representing rolling a1throught6on the dice. The answer isDP[N]. -
Minimizing Coins - The state
DP[i]will represent the minimum number of coins to get a sum ofi. The initial state isDP[0] = 0representing zero coins to get a sum of0, and the transition isDP[i] = min(DP[i - c] + 1)representing using a coin of valuecto get a sum ofifrom the minimum ofi-c. The answer isDP[N]. -
Coin Combinations I - The state
DP[i]will represent the number of ways to get a sum ofiusing the coins. The initial state isDP[0] = 1representing one way to get a sum of0, and the transition isDP[i] = sum(DP[i - c])forcin the coins, representing using a coin of valuecto get a sum ofifrom the sum ofi-c. The answer isDP[N]. -
Coin Combinations II - The state
DP[i][q]will represent the number of ways to get a sum ofqusing the firsticoins. The initial state isDP[0][0] = 1representing one way to get a sum of0using the first0coins, and the transition isDP[i][q] = DP[i - 1][q] + DP[i][q - c]forcin the coins, representing not using theith coin, or using theith coin. The answer isDP[N][X]and this is an example of 0-1 knapsack. -
Removing Digits - The state
DP[i]will represent the minimum number of steps to get fromito0. The initial state isDP[0] = 0representing zero steps to get from0to0, and the transition isDP[i] = min(DP[i - d] + 1)fordin the digits ofi, representing using a digit of valuedto get fromitoi-d. The answer isDP[N]. -
Grid Paths - The state
DP[i][q]will represent the number of ways to get to the cell(i, q). The initial state isDP[0][0] = 1representing one way to get to the cell(0, 0), and the transition isDP[i][q] = DP[i - 1][q] + DP[i][q - 1]representing using the cell above or the cell to the left. Remember to check if the cell is blocked and thus unusable. The answer isDP[N - 1][N - 1]. -
Book Shop - The state
DP[i][q]will represent the maximum number of pages to get withqmoney andibooks. The initial state isDP[0][0] = 0representing zero pages to get with0money and0books, and the transition isDP[i][q] = max(DP[i - 1][q - p] + x, DP[i - 1][q])forpin the prices of the books, representing using theqth book or not. The answer isDP[N][X]. -
Array Description - The state
DP[i][q]will represent the number of ways to have an array ofielements with the last element beingq. The initial state isDP[0][i] = 1ifV[0] = i(value is set toi), orV[0] = 0(value can be anything). The transition isDP[i][q] = sum(DP[i - 1][q - 1], DP[i - 1][q], DP[i - 1][q + 1])forqin the range[1, M]representing the previous element beingq - 1,q, orq + 1. Only apply the transition ifV[i] = 0orV[i] = qwhich means placement is valid. The answer issum(DP[N - 1][q])forqin the range[1, M]representing the different possible last elements. -
Counting Towers - There are two possible ways to build the last layer of the tower. The layer can have two cut/unconnected pieces or two uncut/connected pieces. Let
DP[i][0]represent number of ways to build tower given last layer is cut, andDP[i][0]representing uncut. The initial state isDP[0][0] = 1andDP[0][1] = 1representing one way to build a tower of height0with the last layer cut or uncut. The transition isDP[i][0] = DP[i - 1][1] + 4 * DP[i - 1][0]andDP[i][1] = DP[i - 1][0] + 2 * DP[i - 1][1]representing the different ways to build the last layer. The cut pieces can be combined 4 different ways with an cut layer below it, but only once with an uncut layer. The uncit pieces can be combined once with a cut layer below it, or twice with an uncut layer. The answer isDP[N][0] + DP[N][1]. -
Edit Distance - Given strings
SandT,DP[i][q]represents edit distance betweenS[0..i]andT[0..q]. The initial state isDP[0][0] = 0representing the edit distance between two empty strings. The transition isDP[i][q] = min(DP[i - 1][q] + 1, DP[i][q - 1] + 1, DP[i - 1][q - 1] + (S[i] != T[q]))representing the different ways to edit the strings. The first way is deleting a character from the substring ofT, the second way is deleting a character from the substring ofS, and the third way is replacing a character in the substring ofSwith a character in the substring ofTif needed. The answer isDP[N][M]. -
Rectangle Cutting - The state
DP[i][q]represents minimum number of moves to cut a rectangle of sizei x qinto a square. The initial state isDP[i][i] = 0representing zero moves to cut a rectangle of sizei x iinto a square. The transition isDP[i][q] = min(DP[i - j][q] + DP[j][q] + 1, DP[i][q - j] + DP[i][j] + 1)forjin the range[1, i - 1]representing the different ways to cut the rectangle. The first way is cutting the rectangle horizontally, and the second way is cutting the rectangle vertically. The answer isDP[N][M]. -
Money Sums - The state
DP[i][q]represents if it is possible to create a sum ofqusing the firsticoins. The initial state isDP[0][0] = truerepresenting it is possible to create a sum of0using0coins. The transition isDP[i][q] = DP[i - 1][q] || DP[i - 1][q - V[i]]representing using theith coin or not. The answer are theDP[N][q]that are true. -
Removal Game - The state
DP[i][q]represents the maximum score difference between the first and second player given the coins in the range fromitoq. The initial state isDP[i][i] = V[i]representing the maximum score difference between the first and second player given the coini, as the first player would always take this coin. The transition isDP[i][q] = max(V[i] - DP[i + 1][q], V[q] - DP[i][q - 1])representing the different ways to take a coin. The first way is the first player takes theith coin and the second player, now being the first player ofi+1toqcoins plays optimally. The second way is the first player takes theqth coin and the second player, now being the first player ofitoq-1coins plays optimally. The maximum score difference for player one isDP[0][N - 1], so the maximum score is(sum(V) + DP[0][N - 1]) / 2. Iterate backwards overiand use two pointers, incrementing the right side to iterate overqto fill the DP table. -
Two Sets II - This problem is equivalent to finding the numbers of ways to sum to
N/2using the numbers given, the unused numbers can be used to sum toN/2as well. The stateDP[i][q]represents the number of ways to create a sum ofqusing the firstinumbers. The initial state isDP[0][0] = 1representing one way to create a sum of0using0numbers. The transition isDP[i][q] = DP[i - 1][q] + DP[i - 1][q - i]representing using theith number or not. The answer isDP[N][sum(V) / 2] / 2to prevent double counting, remember to use division under modulo. -
Increasing Subsequence - We will represent the optimal solution as a multiset. Iterate through the numbers. If the number is greater than the end of the multiset, then directly insert it into the multiset. Otherwise, find the smallest number in the multiset that is greater than the current number and replace it with the current number. The answer is the size of the multiset. This works because if the multiset is the optimal solution before the current index, then adding a larger number and increasing the subsequence size is possible, and replacing a number with a smaller number will not decrease the subsequence size, but instead potentially allow for another number to be added later.
-
Projects - This has a simple transition of the current day being the max of yesterday, or the max of the day before the start of the project plus the value of the project. The complexity comes from having to do index compression because we can not iterate across the range
10^9. Index compress and iterate across the compression, instead of the whole range. -
Elevator Rides - The state
DP[i][0]represents minimum number of elevator rides needed to transport the subset of people in the bitwise representation ofi,DP[i][1]represents the weight of the last elevator ride of that subset. The transition is for each person in the subset, get the state without everyone else, and then attempt to add this person to the last elevator ride updating accordingly. Make the current state the minimum of these states. The answer isDP[2^N - 1][0].
-
Counting Rooms - Set up a 2D array where walls are true, and floors are false. Then iterate through whole grid, if the current cell is a floor, then do a DFS to mark all connected floors as visited. Increment the answer by one, and continue iterating through the grid.
-
Labyrinth - Set up a 2D array where walls are true, and floors are false. Start a BFS from the starting cell, and keep track of the previous cell for each cell. When the BFS reaches the end cell, then reconstruct the path by following the previous cell for each cell if possible.
-
Building Roads - We need to connect all the separate connected components of this graph. We can simulate these connected components by adding and uniting a DSU. We can connect every component to the component containing the first city like so. Iterate through the cities, and if the current city is not in the same component as the first city, then connect them and add the road to the answer. The answer is the number of roads added, and the roads added.
-
Message Route - A little overkill, but we can use Dijkstra's starting from the start node. When we add a node to the priority queue, we can keep track of the previous node. When we reach the end node, we can reconstruct the path by following the previous node for each node if possible. The answer is the number of nodes in the path, and the path.
-
Building Teams - Since there are only two colors, we can greedily color the graph using a DFS. For each uncolored node, start a DFS with a certain color and color each child node the opposite color if possible. If we reach a node containing the same color as the parent, then we can not color the graph. Otherwise, we can color the graph. The answer is the color of each node.
-
Round Trip - For each unvisited node, start a DFS and keep track of the previous node. If we reach a node that is already visited, then we have found a cycle. We can reconstruct the cycle by following the previous node for each node if possible. The answer is the number of nodes in the cycle + 1, and the cycle with one node repeated.
-
Monsters - Use BFS to find the shortest distance from a monster to each cell. Then use BFS to find the shortest distance from the starting cell to each cell along with storing the previous node. Only move to a new node if the human distance is smaller than the monster distance. If we reach the end cell, then reconstruct the path by following the previous node for each node if possible. The answer is the number of nodes in the path, and the path.
-
Shortest Routes I - Use Dijkstra's algorithm to find the shortest distance from the starting node to each node. The answer is the distance to each node.
-
Shortest Routes II - Use Floyd-Warshall's algorithm to find the shortest distance from each node to each node. The answer is the distance from each node to each node in the queries.
-
Static Range Sum Queries - Use regular prefix sum, or a sparse table with the addition operation, or a segment tree with the addition operation and integer nodes to answer the queries.
-
Static Range Minimum Queries - Use a sparse table with the minimum operation, or a segment tree with the minimum operation and integer nodes to answer the queries.
-
Dynamic Range Sum Queries - Use a segment tree with the addition operation and integer nodes to answer the queries.
-
Dynamic Range Minimum Queries - Use a segment tree with the minimum operation and integer nodes to answer the queries.
-
Range Xor Queries - Use a segment tree with the xor operation and integer nodes to answer the queries.
-
Range Update Queries - Store a difference array inside a segment tree with the addition operation, you can find the value of each index
iby summing from[0, i]in the difference array. For updates, increment 'a' by 'u' and decrement 'b + 1' by 'u'. -
Forest Queries - Use 2d prefix sums to answer the queries. The answer is the sum of the top left corner and the bottom right corner minus the top right corner and the bottom left corner, where the top left, top right, and bottom left are all shifted one outwards.
-
Hotel Queries - Use a segment tree with the maximum operation and integer nodes. For each query start with
l = 0, r = N-1, and binary search inwards to find the earliest hotel that can fit all guests. If the hotel is found, then update the segment tree and print the index, otherwise, print 0. -
List Removals - Store a
1in every index of the segment tree. For each query start withl = 0, r = N-1, and binary search inwards to find the position that sums tok. Once found, update the segment tree position to0and print the value of the index in the original array. -
Salary Queries - Use an ordered_set whose elements are pairs
{v, i}to store the salaries uniquely. Then uselower_bound,upper_bound, andorder_of_keyto answer the queries. Remember the update both the ordered_set and the original array when updating salaries. -
Prefix Sum Queries - We will use a segment tree with a custom node
{pref: integer, sum: integer}, which will represent the maximum prefix sum and sum of the subarray represented by the segment tree node. The combination operation will sum the two child node sums to get the current node sum, and take the maximum of the left node prefix and the sum of the the left node and right node prefix as the maximum prefix of the current node. Using this logic perform the queries as normal. -
Pizzeria Queries - Consider an arbitrary building
k, all pizzerias at indexibelowkwill have a costc+k-i, and all pizzerias at indexiabovekwill have a costc+i-k. Note that for a givenkas long as we query completely below it or above it, they all have the same addition or subtraction ofk, so we can factor it out. So we will use a segment tree representing belowkstoring nodes of cost and index with the combination operation being the minimum ofc-i, and a segemnt tree representing abovekstoring nodes of cost and index with the combination operation being the minimum ofc+i. Then we can answer the queries by querying the segment tree belowkand the segment tree abovekand taking the minimum of the two. -
Subarray Sum Queries - Using a segment tree in which each node will store the maximum prefix, suffice, sum, and subarray sum of the range it represents. The combination operation will be
pref = max(a.pref, a.sum+b.pref),suff = max(b.suff, b.sum+a.suff),sum = a.sum + b.sum,sub = max(a.sub, b.sub, a.suff+b.pref). Then we can answer the queries as normal by querying the segment tree and returning the subarray sum.
-
Subordinates - Starting from the root of
0perform a DFS down the tree and store the number of subordinates for each node. The subordinates of a nodeuis the sum of the subordinates of all its children and its children. -
Tree Matching - We can consider
DP1[v]as the maximum matching set of the subtree rooted atvwherevis not included in the matching, andDP2[v]as the maximum matching set of the subtree rooted atvwherevis included in the matching. Then we can use a DFS to calculateDP1andDP2for each node. ForDP1we can sum the maximum ofDP1andDP2of each child, and forDP2we choose a child to connect with andDP1of that child, along with the sum of the maximum ofDP1andDP2of each other child plus one. Note you can useDP1ofvto speed up the calculation, but make sure to subtract the right amount from the sum. -
Tree Diameter - If a dfs is started from an arbitrary node and finds the farthest node it will be one of the ends of the diameter of the tree. Then if we start a dfs from that node in a similar fashion, it will reach the other end of the diameter of the tree. The distance between the two nodes will be the diameter of the tree.
-
Tree Distances I - As from the previous problem, we see that if we dfs from an arbitrary node the farthest node is one of the diameters. So for each node we will find its distance from the diameters and then take the maximum. We can do this by finding the diameters, and then performing a dfs from them.
-
Tree Distances II - We can calculate distance from the root node to every other node using a simple dfs, now the observation is that if we shift from the root node to a child node the distances of the nodes in that subtree (lets assume there are
cof them) all decrease by 1, while the distances of the nodes not in that subtree (there would ben-cof them) all increase by 1. So our change from a nodevto one of its children 'x' is equivalent todist[v] + (n-c) - c. We can now dfs down the tree to get all the distances. -
Company Queries I - Direct application of the binary lifting or binary jumping technique. To find the
kth parent of a node, for through its binary representation and jump upwards by2^iif theith bit is set. Make sure to handle the case where the node is not in the tree by returning-1. -
Company Queries II - Direct application of the least common ancestor technique. This can be either be implemented using a segment tree or by using the binary lifting technique like in the previous problem. In the segment tree technique we search for the node that has the least depth in between our first two sightings of the node. In the binary lifting technique we jump upwards while two nodes are ancestors of each other, and the direct parent after this process is the least common ancestor.
-
Distance Queries - The shortest path between two nodes in a tree is to go up to the least common ancestor and then down to the other node. So the distance of this path is
dist[a] + dist[b] - 2*dist[lca(a,b)]. Calculate this using the segment tree technique or the binary lifting technique. -
Counting Paths - The optimal path is the one that goes through the least common ancestor of the two nodes. So we want to increment the count by each of these nodes in this path by
1. One way of doing this efficiently is to process all queries and then perform a dfs where counts from children are added to the parent. So we increment nodesaandbby1, decrement the least common ancestor by1, and decrement the parent of the least common ancestor by1if it exists. If we count upwards using the dfs, this would lead to all nodes in the path incrementing by1and all other nodes remaining unchanged. -
Subtree Queries - This sounds like a segment tree problem, except the problem is that the queries we want to perform are not inherently a contiguous subarray. We have to figure out a way to map the nodes such that a node and its subtrees are contiguous. We can do this by performing a dfs and assigning each node an incrementing counter as the left bound, and when all children are processed we assign the right bound as the current counter value. Now we can perform a segment tree query on the mapped values.
-
Josephus Queries - First observation is that if
2*K <= Nthen the answer is2*K, and if2*K == N+1then the answer is1always. Now consider if these two conditions are not met, in the even case that means we have the remaining sequence of1, 3, ..., and we are trying to find theK-(N+1/2)th number, this is equivalent to the josephus query ofN/2, K-(N+1/2)mapped by2*X-1. In the odd case we have the remaining sequence of3, 5, ..., and we are trying to find theK-(N+1/2)th number, this is equivalent to the josephus query ofN/2, K-(N+1/2)mapped by2*X+1. Thus we can recursively solve this problem following the above logic. -
Exponentiation - Basic application of the binary exponentiation algorithm. Remember to use modular exponentiation to prevent overflow.
-
Exponentiation II - By Fermat's little theorem,
a^(p-1) = 1 mod pifaandpare coprime. Thusa^b^c mod p = a^(b^c mod p-1) mod p, which can be calculated using binary exponentiation and modular exponentiation like above. -
Counting Divisors - If
N = p1^a * p2^b * ...then it has(a+1) * (b+1) * ...factors. We can calculate the prime factorization ofNand then calculate the number of factors using the above formula. -
Common Divisors - We can iterate through the possible divisors from largest
1e6to smallest1. For each divisord, we iterate upwards bydand count all the multiples ofdthat are from the array. If the count is greater than1then we have found a common divisor, and its the largest one since we are iterating downwards. -
Binomial Coefficients - Since the binomial coefficient formula includes multiplication and division of factorials, we can precompute the factorials and their inverses under modulo using modular exponentiation. Then we can calculate the binomial coefficient using the formula given.
-
Creating Strings II - We can order all the letters of a size
Nstring in a total ofN!ways. However, if we have for example5copies ofathen we can exchange them in5!ways and still have the same string. Thus we can divideN!by the product of the factorials of the number of copies of each letter to get the answer. Use modular inverse and precomputation. -
Distributing Apples - We can use the stars and bars method to calculate the number of ways to distribute
Kapples toNpeople. This method entails having a string ofKstars andN-1bars, and counting the number of ways to rearrange them. This is equivalent toN+K-1 choose N-1. Use modular inverse and precomputation. -
Christmas Party - If we consider each child as an index and their gift as a number, then our goal is to permute the standard permutation such that no index is equivalent to its value. This is the derangement problem, and the answer is recursively defined as
D(n) = (n-1)(D(n-1)+D(n-2)). -
Bracket Sequences I - If we consider the first open bracket placed at position
0, and the closing bracket at positioni. Then we can split into two recursive bracket sequences, one inside the first pair, and one after it. Multiply these two calls and sum over our indexi. When written down this formula becomes the Catalan numbers, which can be calculated using modular inverse and precomputation. -
Counting Necklaces - This is an application of Burnside's Lemma, which basically says to find the number of unique elements under a set of transformations, add up the number of unique elements under each transformation and divide by the number of transformations. In this case, there are
Ntransformations of shifts from0toN-1. If we consider a starting position and a given shift, each shift will lead to a chain of connected positions that will be the same color for unique elements. These connected positions continue until they reach thelcm(i, N) = i * N / gcd(i, N), it will reach this by movingieach step, and then repeat. Thus each connected chain is lengthN / gcd(i, N), thus there needs to begcd(i, N)chains to cover every position. Each chain can be any color, so there areM^gcd(i, N)options for each shift. Add up all options and then divide byNunder modulo. -
Counting Grids - This is another application of Burnside's Lemma. This time the number of transformations is
4,0,90,180, and270degrees. The first one allows every square to be colored independently, so we have2^(N^2)options. The second one causes cycles of lengths4, except for the middle element if the size is odd. We haveN * N / 4distinct colors to choose, and the middle one addsN%2, so we get a total of2^(N*N/4 + N%2)options. The third one causes cycles of length2, and the same middle problem, so we have2^(N*N/2 + N%2)options. The final one is exactly the second one but in the opposite direction, so it has the same count. Thus we add all these up and divide by4under modulo and that is our answer.
-
Point Location Test - Direct application of 2d cross product, which is 3rd component of 3d cross product assuming Z coordinate is 0. If cross product of X and Y is positive then X is CCW of Y, negative is CW, and 0 is neither. So if we have a line AB and point C, we can check cross product of AB and AC to get our results using the cases above. For this problem and all continuing geometry problems make sure to keep an eye out for overflow because cross product is doing multiplication.
-
Line Segment Intersection - This is similar to point location test but with more cases. First case is if line segment AB and CD are parallel (can be checked by cross = 0). If they are parallel, then we need to check if they are colinear. If they aren't then no intersection is possible, if they are then just determine if the bounding boxes (boxes formed by min and max x and y coordinates) of each line intersect. If they aren't parallel that means the lines containing AB and CD intersect, but not necessarily the line segments. So we need to check if the intersection point is on both line segments. We can do this by checking if one point of the line segment is to the left of the other line, and the other point is to the right of the other line. If this is true for both lines then the intersection point is on both line segments, otherwise it isn't.
-
Polygon Area - Choose a random point on the polygon, lets choose index 0. If we draw triangles from index 0 to every consecutive pairs of points, the triangles will span the area of the polygon, even if it is concave (cross product will add and subtract from itself). The area of each of these triangles is just cross product of the two vectors divided by 2, however we want twice area, so we don't actually divide by 2. We loop through and add all these areas up and that is our answer.
-
Point In Polygon - First lets determine if a point V is on the boundary of the polygon. To check this we need to check if V is colinear with an arbitrary edge AB (cross product is 0). If its colinear, we just need to check if the point is in the boundary box of that edge. Now if V isn't on the boundary then its either completely inside or completely outside the polygon. Consider a ray drawn from V to some infinite point, if we count the number of sides that this ray intersects we get our answer. If the number is odd the point is inside, else it is outside the polygon. Remember to not use too large of a number for the infinite ray representation to avoid overflow.
-
Polygon Lattice Points - A theorem called Pick's theorem states that A = l + b/2 - 1. Area of a polygon with integer vertices as an expression of lattice points and boundary points. We will double the equation to avoid integer division, we can find 2x area already, so we just need to figure out the number of boundary points. For a given line segment AB we can find points that land on integer coordinates by following the slope (m = y/x), so moving gcd(x, y) to the right, and moving y/x * gcd(x, y) up. So number of coordinates on a line segment is gcd(x, y) + 2, however that will lead to double counting if we do it for every face, so we will do gcd(x, y) + 1, add it all up to get number of boundary points. Then simply apply Pick's theorem.
-
Minimum Euclidean Distance - If we sort the points by X coordinate, we can iterate across the points from left to right and keep a set of points that are within a certain distance by X coordinate. Then for each point we calculate the minimum distance to the points in the set. We can do this by sorting the points by Y coordinate and iterating through the points in the set from bottom to top. This will reduce the time complexity from O(N^2) to O(N log N) as long as we keep the distance small enough. We can do this by making this distance the smallest distance we have encountered so far. Remember to make the initial distance very larger to avoid edge cases.
-
Convex Hull - The Graham Scan algorithm can be used here. Sort the points by X coordinate. The left most point must be in the convex hull. Now if we were just to add points to the hull as we go, the hull will likely not be convex, so to fix this we will backtrack when we find a new point. If we iterate to a new point, and that point is more CCW than the current last point, when compared to the second to last point, then we have to remove the last point in order for the hull to remain convex. This can be checked through cross product of AB and AC, and we can cotninue removing until this newest point is furthest CCW. Now one iteration of this will get the top half of the convex hull, but we can just reverse the points and repeat this to get the bottom half. Remember to remove duplicate points at the end of each half.