Skip to content
Related Articles

Related Articles

Improve Article
Save Article
Like Article

Minimize K to let Person A consume at least ceil(N/(M + 1)) candies based on given rules

  • Difficulty Level : Hard
  • Last Updated : 04 Aug, 2021

Given N candies, M people, and an array arr[] of M positive integers, the task is to find the minimum value of K such that a Person A is able to consume the total of at least ceil of (N/(M + 1)) candies according to the following rules:

  • In the first turn, Person A consumes a minimum of the number of candies left and K.
  • In the next M turns, each ith Person over then range [0, M-1] consumes floor of arr[i] percentage of the remaining candies.
  • Repeat the above steps, until no candies are left.

Examples:

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

Input: N = 13, M = 1, arr[] = {50}
Output: 3
Explanation:
For the value K as 3, the good share is the ceil of (13/2) = 7. Following are the turns that takes place:



  1. Person A takes min(3,13)=3 candies. Therefore, the candies left = 13 – 3 = 10.
  2. Person 0 takes arr[0](= 50)% of the 10 left candies, i.e., 5 candies. Therefore, the candies left = 10 – 5 = 5.
  3. Person A takes min(3,5)=3 candies. Therefore, the candies left = 5 – 3 = 2.
  4. Person 0 takes arr[0](= 50)% of the 2 left candies, i.e., 1 candies. Therefore, the candies left = 2 – 1 = 1.
  5. Person A takes 1 candy. Therefore, the candies left = 1 – 1 = 0.

After the above turns, the candies taken by the person is 3 + 3 + 1 = 7, which is at least (N/(M + 1)) candies, i.e., 13/2 = 6.

Input: N = 13, M = 2, arr[] = {40, 50}
Output: 2

Naive Approach: The simplest approach to solve the given problem is to check for each amount of candies Person A will get for all the possible values of K. Follow the below steps to solve this problem:

  • Find the value of (N/(M + 1)) and stores it in a variable, say good as this is the minimum amount of candies Person A wants to take.
  • Iterate over all the values of K in the range [1, N] and perform the following steps:
    • For each value of K, simulate the process mentioned above and count the total number of candies Person A will get.
    • If the amount of candies is at least the value of good, then break out of the loop. Otherwise, continue the iteration.
  • After completing the above steps, print the current value of K as the result.

Below is the implementation of the above approach: 

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to find minimum value of
// K such that the first person gets
// at least (N/(M+1)) candies
void minimumK(vector<int> &arr, int M,
              int N)
{
    // Find the minimum required value
      // of candies for the first person
    int good = ceil((N * 1.0)
                    / ((M + 1) * 1.0));
 
 
    // Iterate K from [1, n]
    for (int i = 1; i <= N; i++) {
 
          int K = i;
 
          // Total number of candies
        int candies = N;
       
          // Candies taken by Person 1
          int taken = 0;
       
        while (candies > 0) {
           
            // Candies taken by 1st
            // person is minimum of K
            // and candies left         
            taken += min(K, candies);
            candies -= min(K, candies);
 
            // Traverse the array arr[]         
            for (int j = 0; j < M; j++) {
               
                // Amount consumed by the
                  // person j
                int consume = (arr[j]
                               * candies) / 100;
                 
                // Update the number
                  // of candies
                candies -= consume;
            }
        }
 
        // Good share of candies achieved
        if (taken >= good) {
            cout << i;
            return;
        }
    }
}
 
// Driver Code
int main()
{
    int N = 13, M = 1;
    vector<int> arr = { 50 }; 
    minimumK(arr, M, N);
   
      return 0;
}

Java




// Java program for the above approach
import java.util.*;
 
class GFG{
 
// Function to find minimum value of
// K such that the first person gets
// at least (N/(M+1)) candies
static void minimumK(ArrayList<Integer> arr, int M,
                                             int N)
{
     
    // Find the minimum required value
    // of candies for the first person
    int good = (int)((N * 1.0) / ((M + 1) * 1.0)) + 1;
 
    // Iterate K from [1, n]
    for(int i = 1; i <= N; i++)
    {
        int K = i;
 
        // Total number of candies
        int candies = N;
 
        // Candies taken by Person 1
        int taken = 0;
 
        while (candies > 0)
        {
             
            // Candies taken by 1st
            // person is minimum of K
            // and candies left
            taken += Math.min(K, candies);
            candies -= Math.min(K, candies);
 
            // Traverse the array arr[]
            for(int j = 0; j < M; j++)
            {
                 
                // Amount consumed by the
                // person j
                int consume = (arr.get(j) * candies) / 100;
 
                // Update the number
                // of candies
                candies -= consume;
            }
        }
 
        // Good share of candies achieved
        if (taken >= good)
        {
            System.out.print(i);
            return;
        }
    }
}
 
// Driver Code
public static void main(String[] args)
{
    int N = 13, M = 1;
    ArrayList<Integer> arr = new ArrayList<Integer>();
    arr.add(50);
     
    minimumK(arr, M, N);
}
}
 
// This code is contributed by subhammahato348

Python3




# Python 3 program for the above approach
import math
# Function to find minimum value of
# K such that the first person gets
# at least (N/(M+1)) candies
def minimumK(arr,  M, N):
 
    # Find the minimum required value
    # of candies for the first person
    good = math.ceil((N * 1.0) / ((M + 1) * 1.0))
 
    # Iterate K from [1, n]
    for i in range(1, N + 1):
        K = i
 
        # Total number of candies
        candies = N
 
        # Candies taken by Person 1
        taken = 0
 
        while (candies > 0):
 
            # Candies taken by 1st
            # person is minimum of K
            # and candies left
            taken += min(K, candies)
            candies -= min(K, candies)
 
            # Traverse the array arr[]
            for j in range(M):
 
                # Amount consumed by the
                # person j
                consume = (arr[j]
                           * candies) / 100
 
                # Update the number
                # of candies
                candies -= consume
                         
        # Good share of candies achieved
        if (taken >= good):
          print(i)
          return
 
# Driver Code
if __name__ == "__main__":
 
    N = 13
    M = 1
    arr = [50]
    minimumK(arr, M, N)
 
    # This code is contributed by ukasp.

C#




// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
// Function to find minimum value of
// K such that the first person gets
// at least (N/(M+1)) candies
static void minimumK(List<int> arr, int M,
              int N)
{
    // Find the minimum required value
      // of candies for the first person
    int good = (int)((N * 1.0) / ((M + 1) * 1.0))+1;
 
    // Iterate K from [1, n]
    for (int i = 1; i <= N; i++) {
 
          int K = i;
 
          // Total number of candies
          int candies = N;
       
          // Candies taken by Person 1
          int taken = 0;
       
        while (candies > 0) {
           
            // Candies taken by 1st
            // person is minimum of K
            // and candies left         
            taken += Math.Min(K, candies);
            candies -= Math.Min(K, candies);
 
            // Traverse the array arr[]         
            for (int j = 0; j < M; j++) {
               
                // Amount consumed by the
                  // person j
                int consume = (arr[j]
                               * candies) / 100;
                 
                // Update the number
                  // of candies
                candies -= consume;
            }
        }
 
        // Good share of candies achieved
        if (taken >= good) {
            Console.Write(i);
            return;
        }
    }
}
 
// Driver Code
public static void Main()
{
    int N = 13, M = 1;
    List<int> arr = new List<int>();
    arr.Add(50); 
    minimumK(arr, M, N);
}
}
 
// This code is contributed by SURENDRA_GANGWAR.

Javascript




<script>
 
// JavaScript program for the above approach
 
 
// Function to find minimum value of
// K such that the first person gets
// at least (N/(M+1)) candies
function minimumK(arr, M, N)
{
    // Find the minimum required value
   // of candies for the first person
    let good = Math.floor((N * 1.0) / ((M + 1) * 1.0))+1;
 
    // Iterate K from [1, n]
    for (let i = 1; i <= N; i++) {
 
          let K = i;
 
          // Total number of candies
          let candies = N;
       
          // Candies taken by Person 1
          let taken = 0;
       
        while (candies > 0) {
           
            // Candies taken by 1st
            // person is minimum of K
            // and candies left         
            taken += Math.min(K, candies);
            candies -= Math.min(K, candies);
 
            // Traverse the array arr[]         
            for (let j = 0; j < M; j++) {
               
                // Amount consumed by the
                  // person j
                let consume = (arr[j]
                               * candies) / 100;
                 
                // Update the number
                  // of candies
                candies -= consume;
            }
        }
 
        // Good share of candies achieved
        if (taken >= good) {
            document.write(i);
            return;
        }
    }
}
 
// Driver Code
 
    let N = 13, M = 1;
    let arr = new Array();
    arr.push(50); 
    minimumK(arr, M, N);
 
 
// This code is contributed by _Saurabh_Jaiswal
 
</script>

Output:

3

Time Complexity: O(N2)
Auxiliary Space: O(1)

Efficient Approach: The above approach can also be optimized by using Binary Search. Follow the steps below to solve the problem:

  • Find the value of (N/(M + 1)) and stores it in a variable, say good as this is the minimum amount of candies Person A wants to take.
  • Initialize two variables, say low and high as 1 and N respectively.
  • Iterate until low is less than high and perform the following steps:
    • Find the value of mid as (low + high)/2.
    • Find the minimum number of candies taken by Person A for the value of K as mid by simulating the process mentioned above.
    • If the number of candies taken by Person A is at least good then update the value of high as mid. Otherwise, update the value of low as (mid + 1).
  • After completing the above steps, print the value of high as the resultant minimum value of K.

Below is the implementation of the above approach: 

C++




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to check if the value of
// mid gives at least (N/(M + 1))
// candies or not
bool check(int K, int n, int m,
           vector<int> arr,
           int good_share)
{
    int candies = n, taken = 0;
 
    while (candies > 0) {
 
        // Candies taken by 1st
        // person is minimum of K
        // and candies left
        taken += min(K, candies);
        candies -= min(K, candies);
 
        // Traverse the given array
        for (int j = 0; j < m; j++) {
 
            // Amount consumed by
              // person j
            int consume = (arr[j] * candies) / 100;
 
            // Update the count of
              // candies
            candies -= consume;
        }
    }
 
    // Check if person 1 gets the
      // good share of candies
    return (taken >= good_share);
}
 
// Function to find minimum value of
// K such that the first person gets
// at least (N/(M+1)) candies
void minimumK(vector<int> &arr, int N,
              int M)
{
    // Find the minimum required value
      // of candies for the first person
    int good_share = ceil((N * 1.0)
                          / ((M + 1) * 1.0));
 
    int lo = 1, hi = N;
 
      // Iterate until low is less
      // than or equal to mid
    while (lo < hi) {
 
        // Find the value of mid
        int mid = (lo + hi) / 2;
 
        // Check for mid, whether it
          // can be the possible value
          // of K or not
        if (check(mid, N, M, arr,
                  good_share)) {
 
            // Update the value of hi
            hi = mid;
        }
       
          // Otherwise, update the
          // value of lo
        else {
            lo = mid + 1;
        }
    }
 
    // Print the resultant minimum
      // value of K
    cout << hi;
}
 
// Driver Code
int main()
{
    int N = 13, M = 1;
    vector<int> arr = { 50 };
   
    minimumK(arr, N, M);
   
      return 0;
}

Java




// Java program for the above approach
import java.util.*;
 
class GFG {
 
// Function to check if the value of
// mid gives at least (N/(M + 1))
// candies or not
static boolean check(int K, int n, int m,
           ArrayList<Integer> arr,
           int good_share)
{
    int candies = n, taken = 0;
 
    while (candies > 0) {
 
        // Candies taken by 1st
        // person is minimum of K
        // and candies left
        taken += Math.min(K, candies);
        candies -= Math.min(K, candies);
 
        // Traverse the given array
        for (int j = 0; j < m; j++) {
 
            // Amount consumed by
              // person j
            int consume = (arr.get(j) * candies) / 100;
 
            // Update the count of
              // candies
            candies -= consume;
        }
    }
 
    // Check if person 1 gets the
      // good share of candies
    return (taken >= good_share);
}
 
// Function to find minimum value of
// K such that the first person gets
// at least (N/(M+1)) candies
static void minimumK(ArrayList<Integer> arr, int N,
              int M)
{
    // Find the minimum required value
      // of candies for the first person
    int good_share = (int)Math.ceil((N * 1.0)
                          / ((M + 1) * 1.0));
 
    int lo = 1, hi = N;
 
      // Iterate until low is less
      // than or equal to mid
    while (lo < hi) {
 
        // Find the value of mid
        int mid = (lo + hi) / 2;
 
        // Check for mid, whether it
          // can be the possible value
          // of K or not
        if (check(mid, N, M, arr,
                  good_share)) {
 
            // Update the value of hi
            hi = mid;
        }
       
          // Otherwise, update the
          // value of lo
        else {
            lo = mid + 1;
        }
    }
 
    // Print the resultant minimum
      // value of K
    System.out.print(hi);
}
 
// Driver Code
public static void main(String[] args)
{
    int N = 13, M = 1;
    ArrayList<Integer> arr = new ArrayList<Integer>();
    arr.add(50);
   
    minimumK(arr, N, M);
}
}
 
// This code is contributed by avijitmondal1998.

Time Complexity: O(N * log N)
Auxiliary Space: O(1)




My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!