UVALive 7500 Boxes and Balls 2015EC final 签到题 二分

分析题目后,得到要求的是最接近n的一个数,并且这个数字能写成1+2+3+....+x = ans这种形式。

要求的是最大的值。

这题就直接二分去做吧。二分出一个f(mid)<=n的最大值。

最后的end就是所求的f(end)

为什么呢?,我来分析下我这个二分是怎么实现的

   while (begin<=end)
    {
        LL mid = (begin + end) / 2;
        if (f(mid) == n)
        {
            printf ("Case #%d: %lld
",++ff,n);
            return ;
        }
        if (f(mid) < n)
        {
            begin = mid+1; //去找一个可能比n大的
        }
        else end = mid-1; //如果比n大了的话。就回来找一个小的。
        //cout<<f(mid)<<endl;
    }

当f(mid)<n的时候 begin = mid+1,如果这个时候[mid+1,end]的所有数字的f()值都大于n呢?那么,最后一步就肯定是begin=end,然后end-1.去到的是第一个小于n的f()值。

其他也是一样分析啦。

f(end),第一个小于n的f值。

f(begin),第一个大于n的f值。考虑最后一步begin==end的时候,就能看清楚了。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
LL f(LL x)
{
    if (x&1)
    {
        return (x+1)/2*x;
    }
    else return x/2*(x+1);
}
int ff;
void work ()
{
    LL n;
    cin>>n;
    LL begin=1,end=2e9;
    while (begin<=end)
    {
        LL mid = (begin + end) / 2;
        if (f(mid) == n)
        {
            printf ("Case #%d: %lld
",++ff,n);
            return ;
        }
        if (f(mid) < n)
        {
            begin = mid+1; //去找一个可能比n大的
        }
        else end = mid-1; //如果比n大了的话。就回来找一个小的。
        //cout<<f(mid)<<endl;
    }
    printf ("Case #%d: %lld
",++ff,f(end));
    return ;
}

int main()
{
#ifdef local
    freopen("data.txt","r",stdin);
#endif
    int t;
    cin>>t;
    while(t--) work();
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/liuweimingcprogram/p/5785398.html