hdu 5312 三角形形数 二分查找

hdu 5312 三角形数 二分查找

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 nhdu 5312 三角形形数 二分查找-th(n1)hdu 5312 三角形形数 二分查找 item is 3n(n1)+1hdu 5312 三角形形数 二分查找. Now he wants to know if an integer mhdu 5312 三角形形数 二分查找 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+1hdu 5312 三角形形数 二分查找.
 

Input
There are multiple test cases. The first line of input contains an integerThdu 5312 三角形形数 二分查找(1T10hdu 5312 三角形形数 二分查找4hdu 5312 三角形形数 二分查找)hdu 5312 三角形形数 二分查找, indicating the number of test cases. For each test case:

There's a line containing an integer mhdu 5312 三角形形数 二分查找(1m10hdu 5312 三角形形数 二分查找9hdu 5312 三角形形数 二分查找)hdu 5312 三角形形数 二分查找.
 

Output
For each test case, output 1hdu 5312 三角形形数 二分查找 if mhdu 5312 三角形形数 二分查找 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(n1)+1hdu 5312 三角形形数 二分查找,再给一个任意一个数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
BestCoder 1st Anniversary ($)
 

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

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