码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 5312 三角形数 二分查找

时间:2015-07-27 16:31:07      阅读:98      评论:0      收藏:0      [点我收藏+]

标签:

Sequence

Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 891    Accepted Submission(s): 271


Problem Description
Today, Soda has learned a sequence whose n技术分享-th(n1)技术分享 item is 3n(n?1)+1技术分享. Now he wants to know if an integer m技术分享 can be represented as the sum of some items of that sequence. If possible, what are the minimum items needed?

For example, 22=19+1+1+1=7+7+7+1技术分享.
 

Input
There are multiple test cases. The first line of input contains an integerT技术分享(1T10技术分享4技术分享)技术分享, indicating the number of test cases. For each test case:

There‘s a line containing an integer m技术分享(1m10技术分享9技术分享)技术分享.
 

Output
For each test case, output ?1技术分享 if m技术分享 cannot be represented as the sum of some items of that sequence, otherwise output the minimum items needed.
 

Sample Input
10 1 2 3 4 5 6 7 8 22 10
 

Sample Output
1 2 3 4 5 6 1 2 4 4
 题意,给出一个数列3n(n?1)+1技术分享,再给一个任意一个数m,要求最少能用多少个数列中的数之和为m
给出一个规律:n*(n-1)/2是三角形数,任何一个自然数可用最多三个三角形数拼成,这个规律得知道,才可以解出这题。
上式变形得到6*(n * (n-1)/2) + 1;如果,m是由k个数组成,那m不就可以表示成6 * (k个三角形数之和) + k这样的形式了。k个三角形数之和,如果k>
=3,那么,由上面的规律,我们可以马上知道,这样的数肯定是存在的。k = 1 k = 2,要分开讨论。k = 1时,只需要二分找出是数列中的一个数就可以了。
k = 2时,找出 pri[i] + pri[j] = m(pri是给出的数列),这样的i,j是否存在, 一种方法,枚举i,得到m - pri[i] 判定是否在pri中,这样的复杂度是o(n * log(n)),
n是这个数列的个数。显然复杂度太高,我们知道,pri这个数列是递增的,我们可以用这个性质,i = 0 ,j = prilen -1;如果pri[i] + pri[j] > m;j--;否则i++;这
样,一定可以找出来是否和为m且复杂度只能o(n),这样才能过这题。由于i 只会加n次,j也只会减n次,所以总的复杂度为o(N)
为什么这样是对的呢,其实很简单,假设pri[ii]  + pri[jj] = m,这样的方法,会不会,没找到ii,jj呢,不会,
初始 i < ii j>jj;如果pri[i] + pri[j] < m i++,否则j--,
1.假如,i先到达ii,此时,j > jj,pri[i] + pri[j] > pri[ii] + pri[jj] = m ;所以j--,最终一定会是,j = jj;
2.假如,j先到达jj,此时,i < ii,pri[i] + pri[j] < pri[ii] + pri[jj] = m ;所以i++,最终一定会是,i = ii;
所以不管怎么样,一定会找到答案。
#define N 205
#define M 100005
#define maxn 205
#define MOD 1000000000
int n,glen,len,pn,m,pri[M];
set<int> myset;
set<int>::iterator it;
bool solve1(int mm){
    return myset.count(mm);
}
bool solve2(int mm){
    for(int i = 0,j = pn -1;i< pn && pri[i] <= mm;i++){
        while(j>= 0 && pri[i] + pri[j] > mm)j--;
        if(j>=0 && pri[i] + pri[j] == mm) return true;
    }
    return false;
}
int main()
{
    pn = 0;
    for(int i = 1;i< M -1 ;i++){
        int t = 3 * i * (i-1) + 1;
        if(t <= MOD){
            pri[pn++] = t;
            myset.insert(t);
        }
        else break;
    }
    while(S(n)!=EOF)
    {
        while(n--){
            S(m);
            if(m%6 == 1){
                if(solve1(m))
                    printf("1\n");
                else
                    printf("7\n");
                continue;
            }
            else if(m%6 == 2)
            {
                if(solve2(m))
                    printf("2\n");
                else
                    printf("8\n");
                continue;
            }
            else
                printf("%d\n",(m - 1)%6 + 1);
        }
    }
    return 0;
}


Source
 

Recommend
hujie   |   We have carefully selected several similar problems for you:  5315 5314 5310 5309 5308 

版权声明:本文为博主原创文章,未经博主允许不得转载。

hdu 5312 三角形数 二分查找

标签:

原文地址:http://blog.csdn.net/mengzhengnan/article/details/47084661

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!