hdu 5312 三角形数 二分查找

18 篇文章 0 订阅
11 篇文章 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(n1)+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 integer T (1T104) , indicating the number of test cases. For each test case:

There's a line containing an integer m (1m109) .
 

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(n1)+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 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值