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
Explanation: In ,the first turn, the fourth person 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
Explanation: At the second turn first one receives 4 and then we have no more candies left.
Table of Content
[Naive Approach] Progressive Turnwise Distribution - O(N) Time and O(K) Space
We can solve this problem by distributing candies in a cyclic manner. Each person receives candies incrementally: the first person gets 1, the second gets 2, and so on up to K people. In the next cycle, the first person receives K+1, the second gets K+2, and this continues until all candies are distributed.
#include <bits/stdc++.h>
using namespace std;
vector<int> distribute_candies(int N, int K) {
vector<int> result(K, 0);
int i = 0;
while (N > 0) {
int candies_to_give = min(N, i+1);
result[i % K] += candies_to_give;
N -= candies_to_give;
i += 1;
}
return result;
}
int main() {
int N = 10;
int K = 3;
vector<int> result = distribute_candies(N, K);
for (int i = 0; i < K; i++) {
std::cout << result[i] << " ";
}
return 0;
}
import java.util.*;
public class GfG {
public static List<Integer> distribute_candies(int N,
int K)
{
List<Integer> result
= new ArrayList<>(Collections.nCopies(
K, 0));
int i = 0;
while (N > 0) {
int candiesToGive = Math.min(N, i + 1);
result.set(
i % K,
result.get(i % K)
+ candiesToGive);
N -= candiesToGive;
i += 1;
}
return result;
}
public static void main(String[] args)
{
int N = 10;
int K = 3;
List<Integer> result = distribute_candies(N, K);
for (int i = 0; i < K; i++) {
System.out.print(result.get(i) + " ");
}
}
}
def distribute_candies(N, K):
result = [0] * K
i = 0
while N > 0 :
candies_to_give = min(N, i+1)
result[i % K] += candies_to_give
N -= candies_to_give
i += 1
return result
if __name__ == '__main__':
N = 10
K = 3
result = distribute_candies(N, K)
for i in range(K):
print(result[i], end=" ")
# output: 3 3 4
using System;
using System.Collections.Generic;
public class Gfg {
public static List<int> distribute_candies(int N, int K) {
List<int> result = new List<int>(new int[K]);
int i = 0;
while (N > 0) {
int candies_to_give = Math.Min(N, i+1);
result[i % K] += candies_to_give;
N -= candies_to_give;
i += 1;
}
return result;
}
public static void Main() {
int N = 10;
int K = 3;
List<int> result = distribute_candies(N, K);
for (int i = 0; i < K; i++) {
Console.Write(result[i] + " ");
}
}
}
// JavaScript equivalent
function distribute_candies(N, K) {
let result = Array(K).fill(0);
let i = 0;
while (N > 0) {
let candies_to_give = Math.min(N, i+1);
result[i % K] += candies_to_give;
N -= candies_to_give;
i += 1;
}
return result;
}
let N = 10;
let K = 3;
let result = distribute_candies(N, K); temp="";
for (let i = 0; i < K; i++) {
temp = temp+result[i]+" ";
} console.log(temp);
Output
5 2 3
[Better Approach] Using formulas - O(turns + K) Time and O(K) Space
Start with total candies NNN, KKK people, and a turn counter. Distribute candies in increasing order (1, 2, ..., K) while decreasing the remaining candies. After each full cycle, update the turn count and continue. If a full cycle isn’t possible, distribute the remaining candies individually. Finally, use the arithmetic progression formula for efficient distribution and output the result.
#include <bits/stdc++.h>
using namespace std;
// Function to find out the number of
// candies every person received
vector<int> distribute_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
vector<int> arr(k,0);
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
return arr;
}
// Driver Code
int main()
{
int n = 10, k = 3;
vector<int> ans = distribute_candies(n, k);
for(auto it:ans)cout<<it<<" ";
return 0;
}
class GfG {
// Function to find out the number of
// candies every person received
static int[] distribute_candies(int n, int k)
{
int[] arr = new int[k];
int j = 0;
while (n > 0) {
for (int i = 0; i < k; i++) {
j++;
if (n <= 0) {
break;
}
else {
if (j < n) {
arr[i] = arr[i] + j;
}
else {
arr[i] = arr[i] + n;
}
n = n - j;
}
}
}
return arr;
}
// Driver Code
public static void main(String[] args)
{
int n = 10, k = 3;
int[] ans = distribute_candies(n, k);
for(int i=0;i<k;i++)
System.out.print(ans[i] + " ");
}
}
import math as mt
# Function to find out the number of
# candies every person received
def distribute_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
return arr
# Driver Code
n, k = 10, 3
ans = distribute_candies(n, k)
for i in ans:
print(i, end = " ")
using System;
class GfG {
// Function to find out the number of
// candies every person received
static int[] distribute_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
return arr;
}
// Driver Code
public static void Main()
{
int n = 10, k = 3;
int[] ans = distribute_candies(n, k);
for(int i=0;i<k;i++)
Console.Write(ans[i] + " ");
}
}
function distribute_candies(n, k)
{
// Count number of complete turns
var count = 0;
// Get the last term
var ind = 1;
// Stores the number of candies
var arr = Array(k);
for (i = 0; i < k; i++)
arr[i] = 0;
while (n > 0) {
// Last term of last and
// current series
var f1 = (ind - 1) * k;
var f2 = ind * k;
// Sum of current and last series
var sum1 = (f1 * (f1 + 1)) / 2;
var sum2 = (f2 * (f2 + 1)) / 2;
// Sum of current series only
var res = sum2 - sum1;
// If sum of current is less than N
if (res <= n) {
count++;
n -= res;
ind++;
}
else // Individually distribute
{
var i = 0;
// First term
var 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;
}
}
}
}
for (i = 0; i < k; i++)
arr[i] += (count * (i + 1))
+ (k * (count * (count - 1)) / 2);
return arr;
}
var n = 10, k = 3;
let ans = distribute_candies(n, k);
// Count the total candies
// Print the total candies
console.log(ans.slice(0, k).join(" "));
Output
5 2 3
[Expected Approach] Using the binary search - O(logn + K) Time + O(K) Space
Use binary search to find the maximum number of complete turns, then distribute leftover candies from the last incomplete turn using a loop. Finally, apply the arithmetic progression formula to efficiently allocate candies for complete turns.
#include <bits/stdc++.h>
using namespace std;
vector<int> distribute_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
vector<int> arr(k, 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 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
return arr;
}
int main()
{
int n = 10, k = 3;
vector<int> ans = distribute_candies(n, k);
for (auto it : ans)
cout << it << " ";
return 0;
}
class GfG {
static int[] distribute_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);
return arr;
}
// Driver Code
public static void main(String[] args)
{
int n = 10, k = 3;
int[] ans = distribute_candies(n, k);
for (int i = 0; i < k; i++) {
System.out.print(ans[i] + " ");
}
}
}
# Function to find out the number of
# candies every person received
def distribute_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
return arr
# Driver Code
n = 10;
k = 3;
ans = distribute_candies(n, k);
for i in range(k):
print(ans[i], end = " ");
# This code is contributed by chandan_jnu
using System;
class GfG
{
static int[] distribute_candies(int n, int k)
{
// Count number of complete turns
int count = 0;
// 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);
return arr;
}
// Driver Code
public static void Main()
{
int n = 10, k = 3;
int[] ans = distribute_candies(n, k);
for (int i = 0; i < k; i++)
Console.Write( ans[i] + " " );
}
}
function distribute_candies(n, k)
{
// Count number of complete turns
var count = 0;
// Get the last term
var ind = 1;
// Stores the number of candies
var arr = Array(k).fill(0);
for (i = 0; i < k; i++)
arr[i] = 0;
var low = 0, high = n;
// Do a binary search to find the number whose
// sum is less than N.
while (low <= high) {
// Get mide
var mid = parseInt((low + high) / 2);
var sum = parseInt((mid * (mid + 1)) / 2);
// If sum is below N
if (sum <= n) {
// Find number of complete turns
count = parseInt(mid / k);
// Right halve
low = mid + 1;
}
else {
// Left halve
high = mid - 1;
}
}
// Last term of last complete series
var last = (count * k);
// Subtract the sum till
n -= (last * (last + 1)) / 2;
var j = 0;
// First term of incomplete series
var 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 (i = 0; i < k; i++)
arr[i] += (count * (i + 1))
+ (k * (count * (count - 1)) / 2);
return arr;
}
// Driver Code
var n = 10, k = 3;
let ans = distribute_candies(n, k);
console.log(ans.slice(0, k).join(" "));
Output
5 2 3