Distribute N candies among K people

Given N candies and K people. In the first turn, the first person gets 1 candy, the second gets 2 candies, and so on till K people. In the next turn, the first person gets K+1 candies, the second person gets k+2 candies and so on. If the number of candies is less than the required number of candies at every turn, then the person receives the remaining number of candies.

The task is to find the total number of candies every person has at the end.

Examples:

Input: N = 7, K = 4
Output: 1 2 3 1
At the first turn, the fourth people has to be given 4 candies, but there is
only 1 left, hence he takes one only.

Input: N = 10, K = 3
Output: 5 2 3
At the second turn first one receives 4 and then we have no more candies left.

A naive approach is to iterate for every turn and distribute candies accordingly till candies are finished.
Time complexity: O(Number of distributions)

A better approach is to perform every turn in O(1) by calculating sum of natural numbers till the last term of series which will be (turns*k) and subtracting the sum of natural numbers till the last term of previous series which is (turns-1)*k. Keep doing this till the sum is less than N, once it exceeds then distribute candies in the given way till possible. We call a turn completed if every person gets the desired number of candies he is to get in a turn.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ code for better approach
// to distribute candies
#include <bits/stdc++.h>
using namespace std;
  
// Function to find out the number of
// candies every person received
void candies(int n, int k)
{
  
    // Count number of complete turns
    int count = 0;
  
    // Get the last term
    int ind = 1;
  
    // Stores the number of candies
    int arr[k];
  
    memset(arr, 0, sizeof(arr));
  
    while (n) {
  
        // Last term of last and
        // current series
        int f1 = (ind - 1) * k;
        int f2 = ind * k;
  
        // Sum of current and last  series
        int sum1 = (f1 * (f1 + 1)) / 2;
        int sum2 = (f2 * (f2 + 1)) / 2;
  
        // Sum of current series only
        int res = sum2 - sum1;
  
        // If sum of current is less than N
        if (res <= n) {
            count++;
            n -= res;
            ind++;
        }
        else // Individually distribute
        {
            int i = 0;
  
            // First term
            int term = ((ind - 1) * k) + 1;
  
            // Distribute candies till there
            while (n > 0) {
  
                // Candies available
                if (term <= n) {
                    arr[i++] = term;
                    n -= term;
                    term++;
                }
                else // Not available
                {
                    arr[i++] = n;
                    n = 0;
                }
            }
        }
    }
  
    // Count the total candies
    for (int i = 0; i < k; i++)
        arr[i] += (count * (i + 1)) 
                + (k * (count * (count - 1)) / 2);
  
    // Print the total candies
    for (int i = 0; i < k; i++)
        cout << arr[i] << " ";
}
  
// Driver Code
int main()
{
    int n = 10, k = 3;
    candies(n, k);
  
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java  code for better approach
// to distribute candies
  
  
class GFG
{
    // Function to find out the number of
    // candies every person received
    static void candies(int n, int k)
    {
      
        // Count number of complete turns
        int count = 0;
      
        // Get the last term
        int ind = 1;
      
        // Stores the number of candies
        int []arr=new int[k];
      
        for(int i=0;i<k;i++)
         arr[i]=0;
      
        while (n>0) {
      
            // Last term of last and
            // current series
            int f1 = (ind - 1) * k;
            int f2 = ind * k;
      
            // Sum of current and last series
            int sum1 = (f1 * (f1 + 1)) / 2;
            int sum2 = (f2 * (f2 + 1)) / 2;
      
            // Sum of current series only
            int res = sum2 - sum1;
      
            // If sum of current is less than N
            if (res <= n) {
                count++;
                n -= res;
                ind++;
            }
            else // Individually distribute
            {
                int i = 0;
      
                // First term
                int term = ((ind - 1) * k) + 1;
      
                // Distribute candies till there
                while (n > 0) {
      
                    // Candies available
                    if (term <= n) {
                        arr[i++] = term;
                        n -= term;
                        term++;
                    }
                    else // Not available
                    {
                        arr[i++] = n;
                        n = 0;
                    }
                }
            }
        }
      
        // Count the total candies
        for (int i = 0; i < k; i++)
            arr[i] += (count * (i + 1)) 
                    + (k * (count * (count - 1)) / 2);
      
        // Print the total candies
        for (int i = 0; i < k; i++)
            System.out.print( arr[i] + " ");
    }
      
    // Driver Code
    public static void main(String []args)
    {
        int n = 10, k = 3;
        candies(n, k);
      
          
    }
}
  
  
// This code is contributed by ihritik

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 code for better approach
# to distribute candies
import math as mt
  
# Function to find out the number of
# candies every person received
def candies(n, k):
  
    # Count number of complete turns
    count = 0
  
    # Get the last term
    ind = 1
  
    # Stores the number of candies
    arr = [0 for i in range(k)]
  
    while n > 0:
  
        # Last term of last and
        # current series
        f1 = (ind - 1) * k
        f2 = ind * k
  
        # Sum of current and last series
        sum1 = (f1 * (f1 + 1)) // 2
        sum2 = (f2 * (f2 + 1)) //2
  
        # Sum of current series only
        res = sum2 - sum1
  
        # If sum of current is less than N
        if (res <= n):
            count += 1
            n -= res
            ind += 1
        else: # Individually distribute
            i = 0
  
            # First term
            term = ((ind - 1) * k) + 1
  
            # Distribute candies till there
            while (n > 0):
  
                # Candies available
                if (term <= n):
                    arr[i] = term
                    i += 1
                    n -= term
                    term += 1
                else:
                    arr[i] = n
                    i += 1
                    n = 0
  
    # Count the total candies
    for i in range(k):
        arr[i] += ((count * (i + 1)) + 
                   (k * (count * (count - 1)) // 2))
  
    # Print the total candies
    for i in range(k):
        print(arr[i], end = " ")
  
# Driver Code
n, k = 10, 3
candies(n, k)
  
# This code is contributed by Mohit kumar

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# code for better approach
// to distribute candies
  
using System;
class GFG
{
    // Function to find out the number of
    // candies every person received
    static void candies(int n, int k)
    {
      
        // Count number of complete turns
        int count = 0;
      
        // Get the last term
        int ind = 1;
      
        // Stores the number of candies
        int []arr=new int[k];
      
        for(int i=0;i<k;i++)
         arr[i]=0;
      
        while (n>0) {
      
            // Last term of last and
            // current series
            int f1 = (ind - 1) * k;
            int f2 = ind * k;
      
            // Sum of current and last series
            int sum1 = (f1 * (f1 + 1)) / 2;
            int sum2 = (f2 * (f2 + 1)) / 2;
      
            // Sum of current series only
            int res = sum2 - sum1;
      
            // If sum of current is less than N
            if (res <= n) {
                count++;
                n -= res;
                ind++;
            }
            else // Individually distribute
            {
                int i = 0;
      
                // First term
                int term = ((ind - 1) * k) + 1;
      
                // Distribute candies till there
                while (n > 0) {
      
                    // Candies available
                    if (term <= n) {
                        arr[i++] = term;
                        n -= term;
                        term++;
                    }
                    else // Not available
                    {
                        arr[i++] = n;
                        n = 0;
                    }
                }
            }
        }
      
        // Count the total candies
        for (int i = 0; i < k; i++)
            arr[i] += (count * (i + 1)) 
                    + (k * (count * (count - 1)) / 2);
      
        // Print the total candies
        for (int i = 0; i < k; i++)
            Console.Write( arr[i] + " ");
    }
      
    // Driver Code
    public static void Main()
    {
        int n = 10, k = 3;
        candies(n, k);
      
          
    }
}
  
  
// This code is contributed by ihritik

chevron_right


PHP

filter_none

edit
close

play_arrow

link
brightness_4
code

<?php
// PHP code for better approach 
// to distribute candies 
  
// Function to find out the number of 
// candies every person received 
function candies($n, $k
  
    // Count number of complete turns 
    $count = 0; 
  
    // Get the last term 
    $ind = 1; 
  
    // Stores the number of candies 
    $arr = array_fill(0, $k, 0) ;
      
    while ($n
    
  
        // Last term of last and 
        // current series 
        $f1 = ($ind - 1) * $k
        $f2 = $ind * $k
  
        // Sum of current and last series 
        $sum1 = floor(($f1 * ($f1 + 1)) / 2); 
        $sum2 = floor(($f2 * ($f2 + 1)) / 2); 
  
        // Sum of current series only 
        $res = $sum2 - $sum1
  
        // If sum of current is less than N 
        if ($res <= $n
        
            $count++; 
            $n -= $res
            $ind++; 
        
        else // Individually distribute 
        
            $i = 0; 
  
            // First term 
            $term = (($ind - 1) * $k) + 1; 
  
            // Distribute candies till there 
            while ($n > 0) 
            
  
                // Candies available 
                if ($term <= $n
                
                    $arr[$i++] = $term
                    $n -= $term
                    $term++; 
                
                else // Not available 
                
                    $arr[$i++] = $n
                    $n = 0; 
                
            
        
    
  
    // Count the total candies 
    for ($i = 0; $i < $k; $i++) 
        $arr[$i] += floor(($count * ($i + 1)) + ($k *
                          ($count * ($count - 1)) / 2)); 
  
    // Print the total candies 
    for ($i = 0; $i < $k; $i++) 
        echo $arr[$i], " ";
  
// Driver Code 
$n = 10;
$k = 3; 
candies($n, $k);
  
// This code is contributed by Ryuga
?>

chevron_right


Output:

5 2 3

Time complexity: O(Number of turns + K)

An efficient approach is to find the largest number(say MAXI) whose sum upto natural numbers is less than N using Binary search. Since the last number will always be a multiple of K, we get the last number of complete turn. Subtract the summation till then from N. Distribute the remaining candies by traversing in the array.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of the above approach
#include <bits/stdc++.h>
using namespace std;
  
// Function to find out the number of
// candies every person received
void candies(int n, int k)
{
  
    // Count number of complete turns
    int count = 0;
  
    // Get the last term
    int ind = 1;
  
    // Stores the number of candies
    int arr[k];
  
    memset(arr, 0, sizeof(arr));
  
    int low = 0, high = n;
  
    // Do a binary search to find the number whose
    // sum is less than N.
    while (low <= high) {
  
        // Get mide
        int mid = (low + high) >> 1;
        int sum = (mid * (mid + 1)) >> 1;
  
        // If sum is below N
        if (sum <= n) {
  
            // Find number of complete turns
            count = mid / k;
  
            // Right halve
            low = mid + 1;
        }
        else {
  
            // Left halve
            high = mid - 1;
        }
    }
  
    // Last term of last complete series
    int last = (count * k);
  
    // Subtract the sum till
    n -= (last * (last + 1)) / 2;
  
    int i = 0;
  
    // First term of incomplete series
    int term = (count * k) + 1;
  
    while (n) {
        if (term <= n) {
            arr[i++] = term;
            n -= term;
            term++;
        }
        else {
            arr[i] += n;
            n = 0;
        }
    }
  
    // Count the total candies
    for (int i = 0; i < k; i++)
        arr[i] += (count * (i + 1))
               + (k * (count * (count - 1)) / 2);
  
    // Print the total candies
    for (int i = 0; i < k; i++)
        cout << arr[i] << " ";
}
  
// Driver Code
int main()
{
    int n = 7, k = 4;
    candies(n, k);
  
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java implementation of the above approach
  
class GFG
{
    // Function to find out the number of
    // candies every person received
    static void candies(int n, int k)
    {
      
        // Count number of complete turns
        int count = 0;
      
        // Get the last term
        int ind = 1;
      
        // Stores the number of candies
        int []arr=new int[k];
       
        for(int i=0;i<k;i++)
         arr[i]=0;
       
      
        int low = 0, high = n;
      
        // Do a binary search to find the number whose
        // sum is less than N.
        while (low <= high) {
      
            // Get mide
            int mid = (low + high) >> 1;
            int sum = (mid * (mid + 1)) >> 1;
      
            // If sum is below N
            if (sum <= n) {
      
                // Find number of complete turns
                count = mid / k;
      
                // Right halve
                low = mid + 1;
            }
            else {
      
                // Left halve
                high = mid - 1;
            }
        }
      
        // Last term of last complete series
        int last = (count * k);
      
        // Subtract the sum till
        n -= (last * (last + 1)) / 2;
      
        int j = 0;
      
        // First term of incomplete series
        int term = (count * k) + 1;
      
        while (n > 0) {
            if (term <= n) {
                arr[j++] = term;
                n -= term;
                term++;
            }
            else {
                arr[j] += n;
                n = 0;
            }
        }
      
        // Count the total candies
        for (int i = 0; i < k; i++)
            arr[i] += (count * (i + 1))
                + (k * (count * (count - 1)) / 2);
      
        // Print the total candies
        for (int i = 0; i < k; i++)
            System.out.print( arr[i] + " " );
    }
      
    // Driver Code
    public static void main(String []args)
    {
        int n = 7, k = 4;
        candies(n, k);
      
          
    }
  
}
  
// This code is contributed by ihritik

chevron_right


Python3

# Python3 implementation of the above approach

# Function to find out the number of
# candies every person received
def candies(n, k):

# Count number of complete turns
count = 0;

# Get the last term
ind = 1;

# Stores the number of candies
arr = [0] * k;

low = 0;
high = n;

# Do a binary search to find the
# number whose sum is less than N.
while (low <= high): # Get mide mid = (low + high) >> 1;
sum = (mid * (mid + 1)) >> 1;

# If sum is below N
if (sum <= n): # Find number of complete turns count = int(mid / k); # Right halve low = mid + 1; else: # Left halve high = mid - 1; # Last term of last complete series last = (count * k); # Subtract the sum till n -= int((last * (last + 1)) / 2); i = 0; # First term of incomplete series term = (count * k) + 1; while (n): if (term <= n): arr[i] = term; i += 1; n -= term; term += 1; else: arr[i] += n; n = 0; # Count the total candies for i in range(k): arr[i] += ((count * (i + 1)) + int(k * (count * (count - 1)) / 2)); # Print the total candies for i in range(k): print(arr[i], end = " "); # Driver Code n = 7; k = 4; candies(n, k); # This code is contributed by chandan_jnu [tabby title="C#"]

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# implementation of the above approach
  
using System;
class GFG
{
    // Function to find out the number of
    // candies every person received
    static void candies(int n, int k)
    {
      
        // Count number of complete turns
        int count = 0;
      
        // Get the last term
        int ind = 1;
      
        // Stores the number of candies
        int []arr=new int[k];
       
        for(int i=0;i<k;i++)
         arr[i]=0;
       
      
        int low = 0, high = n;
      
        // Do a binary search to find the number whose
        // sum is less than N.
        while (low <= high) {
      
            // Get mide
            int mid = (low + high) >> 1;
            int sum = (mid * (mid + 1)) >> 1;
      
            // If sum is below N
            if (sum <= n) {
      
                // Find number of complete turns
                count = mid / k;
      
                // Right halve
                low = mid + 1;
            }
            else {
      
                // Left halve
                high = mid - 1;
            }
        }
      
        // Last term of last complete series
        int last = (count * k);
      
        // Subtract the sum till
        n -= (last * (last + 1)) / 2;
      
        int j = 0;
      
        // First term of incomplete series
        int term = (count * k) + 1;
      
        while (n > 0) {
            if (term <= n) {
                arr[j++] = term;
                n -= term;
                term++;
            }
            else {
                arr[j] += n;
                n = 0;
            }
        }
      
        // Count the total candies
        for (int i = 0; i < k; i++)
            arr[i] += (count * (i + 1))
                + (k * (count * (count - 1)) / 2);
      
        // Print the total candies
        for (int i = 0; i < k; i++)
            Console.Write( arr[i] + " " );
    }
      
    // Driver Code
    public static void Main()
    {
        int n = 7, k = 4;
        candies(n, k);
      
          
    }
  
}
  
// This code is contributed by ihritik

chevron_right


PHP

filter_none

edit
close

play_arrow

link
brightness_4
code

<?php
// PHP implementation of the above approach
  
// Function to find out the number of
// candies every person received
function candies($n, $k)
{
  
    // Count number of complete turns
    $count = 0;
  
    // Get the last term
    $ind = 1;
  
    // Stores the number of candies
    $arr = array_fill(0, $k, 0);
  
    $low = 0;
    $high = $n;
  
    // Do a binary search to find the 
    // number whose sum is less than N.
    while ($low <= $high
    {
  
        // Get mide
        $mid = ($low + $high) >> 1;
        $sum = ($mid * ($mid + 1)) >> 1;
  
        // If sum is below N
        if ($sum <= $n
        {
  
            // Find number of complete turns
            $count = (int)($mid / $k);
  
            // Right halve
            $low = $mid + 1;
        }
        else
        {
  
            // Left halve
            $high = $mid - 1;
        }
    }
  
    // Last term of last complete series
    $last = ($count * $k);
  
    // Subtract the sum till
    $n -= (int)(($last * ($last + 1)) / 2);
  
    $i = 0;
  
    // First term of incomplete series
    $term = ($count * $k) + 1;
  
    while ($n
    {
        if ($term <= $n
        {
            $arr[$i++] = $term;
            $n -= $term;
            $term++;
        }
        else 
        {
            $arr[$i] += $n;
            $n = 0;
        }
    }
  
    // Count the total candies
    for ($i = 0; $i < $k; $i++)
        $arr[$i] += ($count * ($i + 1)) + 
         (int)($k * ($count * ($count - 1)) / 2);
  
    // Print the total candies
    for ($i = 0; $i < $k; $i++)
        echo $arr[$i] . " ";
}
  
// Driver Code
$n = 7;
$k = 4;
candies($n, $k);
  
// This code is contributed
// by chandan_jnu
?>

chevron_right


Output:

1 2 3 1

Time Complexity: O(log N + K)



My Personal Notes arrow_drop_up