Fork me on GitHub

2014 Super Training #7 B Continuous Login --二分

原题:ZOJ 3768 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3768

一个结论:一个正整数总能用不超过三个前n项相加表示。

先找一个的,在找两个,三个的,二分找,用lower_bound函数。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <vector>
using namespace std;
#define N 16007

int sum[N];

void init()
{
    sum[0] = 0;
    for(int i=1;i<16000;i++)
        sum[i] = sum[i-1] + i;
}

int main()
{
    int t,n,i,j;
    init();
    int a,b;
    int x,y,z;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        int flag = 0;
        int t = lower_bound(sum,sum+16000,n)-sum;
        if(sum[t] == n)
        {
            printf("%d\n",t);
            continue;
        }
        for(i=t;i&&2*sum[i]>=n;i--)
        {
            if(flag == 2)
                break;
            int lef = n-sum[i];
            int t2 = lower_bound(sum,sum+16000,lef)-sum;
            for(j=t2;j&&sum[i]+sum[j]*2>=n;j--)
            {
                if(flag == 2)
                    break;
                if(sum[i]+sum[j]==n)
                {
                    flag = 2;
                    a = i,b = j;
                    break;
                }
                else if(flag == 3)
                    break;
                else if(sum[i]+sum[j]<n)
                {
                    int lef2 = n-sum[i]-sum[j];
                    int t3 = lower_bound(sum,sum+16000,lef2)-sum;
                    if(sum[t3] == lef2)
                    {
                        flag = 3;
                        x = i,y = j,z = t3;
                        break;
                    }
                }
            }
        }
        if(flag == 2)
            printf("%d %d\n",a,b);
        else if(flag == 3)
            printf("%d %d %d\n",x,y,z);
    }
    return 0;
}
View Code

 

posted @ 2014-07-09 19:02  whatbeg  阅读(211)  评论(0编辑  收藏  举报