📜  储罐将变空的天数

📅  最后修改于: 2021-04-24 19:32:33             🧑  作者: Mango

给定容量为C升的油箱,该油箱在启动时已完全充满。每天的水箱中都装有1升水,万一发生溢流,多余的水就会倒出。现在,在第i天,我要取出几公升的水来饮用。我们需要找出罐第一次变空的日期。

例子:

Input : Capacity = 5        
        l = 2
Output : 4
At the start of 1st day, water in tank = 5    
and at the end of the 1st day = (5 - 1) = 4
At the start of 2nd day, water in tank = 4 + 2 = 6
but tank capacity is 5 so water = 5
and at the end of the 2nd day = (5 - 2) = 3
At the start of 3rd day, water in tank = 3 + 2 = 5
and at the end of the 3rd day = (5 - 3) = 2
At the start of 4th day, water in tank = 2 + 2 = 4
and at the end of the 4th day = (4 - 4) = 0
    So final answer will be 4

我们可以看到水箱在开始(l +1)天将充满,因为取出的水少于注入的水。此后,水箱中的水每天将减少1升,并且在第(l +1 + i)天(C –(i)(i +1)/ 2)升水将被保留,不能再喝水。
现在我们需要找到一个最小的天数(l +1 + K),其中即使在将水箱注满l升后,水箱中的水也少于l,即在第(l +1 + K – 1)天,水箱变空了所以我们的目标是找到最小的K,这样,
C – K(K +1)/ 2 <= l

我们可以使用二进制搜索来求解上述方程,然后(l + K)将是我们的答案。解决方案的总时间复杂度将为O(log C)

C++
// C/C++ code to find number of days after which
// tank will become empty
#include 
using namespace std;
  
// Utility method to get sum of first n numbers
int getCumulateSum(int n)
{
    return (n * (n + 1)) / 2;
}
  
// Method returns minimum number of days after 
// which tank will become empty
int minDaysToEmpty(int C, int l)
{
    // if water filling is more than capacity then
    // after C days only tank will become empty
    if (C <= l) 
        return C;    
  
    // initialize binary search variable
    int lo = 0;
    int hi = 1e4;
    int mid;
  
    // loop until low is less than high
    while (lo < hi) {
        mid = (lo + hi) / 2;
  
        // if cumulate sum is greater than (C - l) 
        // then search on left side
        if (getCumulateSum(mid) >= (C - l)) 
            hi = mid;
          
        // if (C - l) is more then search on
        // right side
        else 
            lo = mid + 1;        
    }
  
    // final answer will be obtained by adding
    // l to binary search result
    return (l + lo);
}
  
// Driver code to test above methods
int main()
{
    int C = 5;
    int l = 2;
  
    cout << minDaysToEmpty(C, l) << endl;
    return 0;
}


Java
// Java code to find number of days after which
// tank will become empty
public class Tank_Empty {
      
    // Utility method to get sum of first n numbers
    static int getCumulateSum(int n)
    {
        return (n * (n + 1)) / 2;
    }
       
    // Method returns minimum number of days after 
    // which tank will become empty
    static int minDaysToEmpty(int C, int l)
    {
        // if water filling is more than capacity then
        // after C days only tank will become empty
        if (C <= l) 
            return C;    
       
        // initialize binary search variable
        int lo = 0;
        int hi = (int)1e4;
        int mid;
       
        // loop until low is less than high
        while (lo < hi) {
              
            mid = (lo + hi) / 2;
       
            // if cumulate sum is greater than (C - l) 
            // then search on left side
            if (getCumulateSum(mid) >= (C - l)) 
                hi = mid;
               
            // if (C - l) is more then search on
            // right side
            else
                lo = mid + 1;        
        }
       
        // final answer will be obtained by adding
        // l to binary search result
        return (l + lo);
    }
       
    // Driver code to test above methods
    public static void main(String args[])
    {
        int C = 5;
        int l = 2;
       
        System.out.println(minDaysToEmpty(C, l));
    }
}
// This code is contributed by Sumit Ghosh


Python3
# Python3 code to find number of days 
# after which tank will become empty
  
# Utility method to get
# sum of first n numbers
def getCumulateSum(n):
  
    return int((n * (n + 1)) / 2)
  
  
# Method returns minimum number of days
# after  which tank will become empty
def minDaysToEmpty(C, l):
  
    # if water filling is more than 
    # capacity then after C days only
    # tank will become empty
    if (C <= l) : return C 
  
    # initialize binary search variable
    lo, hi = 0, 1e4
  
    # loop until low is less than high
    while (lo < hi): 
        mid = int((lo + hi) / 2)
  
        # if cumulate sum is greater than (C - l) 
        # then search on left side
        if (getCumulateSum(mid) >= (C - l)): 
            hi = mid
          
        # if (C - l) is more then 
        # search on right side
        else:
            lo = mid + 1    
      
    # Final answer will be obtained by 
    # adding l to binary search result
    return (l + lo)
  
# Driver code
C, l = 5, 2
print(minDaysToEmpty(C, l))
  
# This code is contributed by Smitha Dinesh Semwal.


C#
// C# code to find number 
// of days after which
// tank will become empty
using System;
  
class GFG
{
      
    // Utility method to get
    // sum of first n numbers
    static int getCumulateSum(int n)
    {
        return (n * (n + 1)) / 2;
    }
      
    // Method returns minimum 
    // number of days after 
    // which tank will become empty
    static int minDaysToEmpty(int C, 
                              int l)
    {
        // if water filling is more 
        // than capacity then after 
        // C days only tank will
        // become empty
        if (C <= l) 
            return C; 
      
        // initialize binary 
        // search variable
        int lo = 0;
        int hi = (int)1e4;
        int mid;
      
        // loop until low is
        // less than high
        while (lo < hi) 
        {
              
            mid = (lo + hi) / 2;
      
            // if cumulate sum is 
            // greater than (C - l) 
            // then search on left side
            if (getCumulateSum(mid) >= (C - l)) 
                hi = mid;
              
            // if (C - l) is more then 
            // search on right side
            else
                lo = mid + 1; 
        }
      
        // final answer will be
        // obtained by adding
        // l to binary search result
        return (l + lo);
    }
      
    // Driver code 
    static public void Main ()
    {
        int C = 5;
        int l = 2;
  
        Console.WriteLine(minDaysToEmpty(C, l));
    }
}
  
// This code is contributed by ajit


C++
// C/C++ code to find number of days after which
// tank will become empty
#include 
using namespace std;
  
// Method returns minimum number of days after 
// which tank will become empty
int minDaysToEmpty(int C, int l)
{
    if (l >= C) 
        return C;
      
    double eq_root = (std::sqrt(1+8*(C-l)) - 1) / 2;
    return std::ceil(eq_root) + l;
}
  
// Driver code to test above methods
int main()
{
    cout << minDaysToEmpty(5, 2) << endl;
    cout << minDaysToEmpty(6514683, 4965) << endl;
    return 0;
}


Java
// Java code to find number of days 
// after which tank will become empty
import java.lang.*;
class GFG {
      
// Method returns minimum number of days
// after which tank will become empty
static int minDaysToEmpty(int C, int l)
{
    if (l >= C) return C;
      
    double eq_root = (Math.sqrt(1 + 8 *
                     (C - l)) - 1) / 2;
    return (int)(Math.ceil(eq_root) + l);
}
  
// Driver code
public static void main(String[] args)
{
    System.out.println(minDaysToEmpty(5, 2));
    System.out.println(minDaysToEmpty(6514683, 4965));
}
}
  
// This code is contributed by Smitha Dinesh Semwal.


Python3
# Python3 code to find number of days 
# after which tank will become empty
import math
  
# Method returns minimum number of days  
# after which tank will become empty
def minDaysToEmpty(C, l):
  
    if (l >= C): return C
      
    eq_root = (math.sqrt(1 + 8 * (C - l)) - 1) / 2
    return math.ceil(eq_root) + l
  
# Driver code
print(minDaysToEmpty(5, 2))
print(minDaysToEmpty(6514683, 4965))
  
# This code is contributed by Smitha Dinesh Semwal.


C#
// C# code to find number 
// of days after which 
// tank will become empty
using System;
  
class GFG
{
      
// Method returns minimum 
// number of days after 
// which tank will become empty
static int minDaysToEmpty(int C, 
                          int l)
{
    if (l >= C) return C;
      
    double eq_root = (Math.Sqrt(1 + 8 *
                     (C - l)) - 1) / 2;
    return (int)(Math.Ceiling(eq_root) + l);
}
  
// Driver code
static public void Main ()
{
    Console.WriteLine(minDaysToEmpty(5, 2));
    Console.WriteLine(minDaysToEmpty(6514683,
                                     4965));
}
}
  
// This code is contributed by ajit


PHP
= $C) 
        return $C;
      
    $eq_root = (int)sqrt(1 + 8 * 
                   ($C - $l) - 1) / 2;
    return ceil($eq_root) + $l;
}
  
// Driver code 
echo minDaysToEmpty(5, 2), "\n";
echo minDaysToEmpty(6514683, 
                    4965), "\n";
  
// This code is contributed 
// by akt_mit
?>


输出:

4

替代解决方案:
可以用一个简单的公式在数学上求解:

假设C> L。设d为第L储罐倒空后的天数,在此期间将进行(d-1)加注和d次抽出。
因此,我们需要解决这个方程:
C+(d-1)*L=\sum_{i=1}^{d} Withdrawal_i所有提款的总和是算术级数的总和,因此:
C+(d-1)*L=\frac {L+1+L+d}{2}*2
2C +2dL - 2L=2dL+d +d^2
d^2+d-2(C-L)=0判别= 1 + 8(CL)> 0,因为C> L。
跳过负根,我们得到以下公式:
d=-1 +\frac { \sqrt{1-8(C-L)} }{2}
因此,最后的允许条件是:
min,days=L +ceil\left (  \frac { \sqrt{1-8(C-L)}-1 }{2}\right )

C++

// C/C++ code to find number of days after which
// tank will become empty
#include 
using namespace std;
  
// Method returns minimum number of days after 
// which tank will become empty
int minDaysToEmpty(int C, int l)
{
    if (l >= C) 
        return C;
      
    double eq_root = (std::sqrt(1+8*(C-l)) - 1) / 2;
    return std::ceil(eq_root) + l;
}
  
// Driver code to test above methods
int main()
{
    cout << minDaysToEmpty(5, 2) << endl;
    cout << minDaysToEmpty(6514683, 4965) << endl;
    return 0;
}

Java

// Java code to find number of days 
// after which tank will become empty
import java.lang.*;
class GFG {
      
// Method returns minimum number of days
// after which tank will become empty
static int minDaysToEmpty(int C, int l)
{
    if (l >= C) return C;
      
    double eq_root = (Math.sqrt(1 + 8 *
                     (C - l)) - 1) / 2;
    return (int)(Math.ceil(eq_root) + l);
}
  
// Driver code
public static void main(String[] args)
{
    System.out.println(minDaysToEmpty(5, 2));
    System.out.println(minDaysToEmpty(6514683, 4965));
}
}
  
// This code is contributed by Smitha Dinesh Semwal.

Python3

# Python3 code to find number of days 
# after which tank will become empty
import math
  
# Method returns minimum number of days  
# after which tank will become empty
def minDaysToEmpty(C, l):
  
    if (l >= C): return C
      
    eq_root = (math.sqrt(1 + 8 * (C - l)) - 1) / 2
    return math.ceil(eq_root) + l
  
# Driver code
print(minDaysToEmpty(5, 2))
print(minDaysToEmpty(6514683, 4965))
  
# This code is contributed by Smitha Dinesh Semwal.

C#

// C# code to find number 
// of days after which 
// tank will become empty
using System;
  
class GFG
{
      
// Method returns minimum 
// number of days after 
// which tank will become empty
static int minDaysToEmpty(int C, 
                          int l)
{
    if (l >= C) return C;
      
    double eq_root = (Math.Sqrt(1 + 8 *
                     (C - l)) - 1) / 2;
    return (int)(Math.Ceiling(eq_root) + l);
}
  
// Driver code
static public void Main ()
{
    Console.WriteLine(minDaysToEmpty(5, 2));
    Console.WriteLine(minDaysToEmpty(6514683,
                                     4965));
}
}
  
// This code is contributed by ajit

的PHP

= $C) 
        return $C;
      
    $eq_root = (int)sqrt(1 + 8 * 
                   ($C - $l) - 1) / 2;
    return ceil($eq_root) + $l;
}
  
// Driver code 
echo minDaysToEmpty(5, 2), "\n";
echo minDaysToEmpty(6514683, 
                    4965), "\n";
  
// This code is contributed 
// by akt_mit
?>

输出 :

4
8573

感谢Andrey Khayrutdinov提出了此解决方案。