C. Increase and Copy

C. Increase and Copy

Initially, you have the array aa consisting of one element 11 (a=[1]a=[1]).

In one move, you can do one of the following things:

  • Increase some (single) element of aa by 11 (choose some ii from 11 to the current length of aa and increase aiai by one);
  • Append the copy of some (single) element of aa to the end of the array (choose some ii from 11 to the current length of aa and append aiai to the end of the array).

For example, consider the sequence of five moves:

  1. You take the first element a1a1, append its copy to the end of the array and get a=[1,1]a=[1,1].
  2. You take the first element a1a1, increase it by 11 and get a=[2,1]a=[2,1].
  3. You take the second element a2a2, append its copy to the end of the array and get a=[2,1,1]a=[2,1,1].
  4. You take the first element a1a1, append its copy to the end of the array and get a=[2,1,1,2]a=[2,1,1,2].
  5. You take the fourth element a4a4, increase it by 11 and get a=[2,1,1,3]a=[2,1,1,3].

Your task is to find the minimum number of moves required to obtain the array with the sum at least n.

You have to answer tt independent test cases.

Link:http://codeforces.com/contest/1426/problem/C

 

啊,好久没做cf了。

注意题目要求是at least n,而不是is n。

最快的策略应该是通过+1得到一个较大的数m,然后不断copy m得到一个全是m的数列,直到数列和大于等于n。

假设最初的1通过 i 次+1,最终得到m,即

(1) m = 1 + i

然后 j 次copy m,得到的数列中有j + 1个m,即

(2) n <= m * (j + 1)

题目所求是(i + j)的最小值,也就是m + (j + 1)的最小值。

(2)看起来还不是那么直观,我们通常碰到的一个问题是:已知a,且a = b * c,那么 b 和 c 如何取值能使得b + c最小?

显然当b 和 c 尽可能接近时,即都为sqrt(a)时,b + c 最小。

所以回到(2),我们也尝试取m和 j + 1为sqrt(n),然后再分情况调整即可。

 

AC代码:

#include <iostream>
#include <cmath>
using namespace std;

int main()
{
    int t, n;

    cin >> t;
    while (t--)
    {
        cin >> n;

        // 令m和j+1都是(int)sqrt((double)n)
        int m = sqrt((double)n);
        if (m * m == n)
            cout << 2 * (m - 1) << endl;
        else if (m * (m + 1) >= n)
            cout << 2 * m - 1 << endl;
        // m * (m + 1) < n (and m * m < n)
        else
            cout << 2 * m << endl;
    }

    return 0;
}

 

 

 

 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值