标签:
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
(n≥1)
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
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
Sample Output
题意,给出一个数列
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