【解题思路】
若直接用枚举搜索,所遍历的可能性将会超过10^40000,肯定会超时,需要从中找寻规律。
从最简单的开始:
数字序列 1 能够生成的非负整数为 +1=1,集合为{1}
数字序列 1 2 能够生成的非负整数为 +1+2=3,-1+2=1,集合为{1,3}
数字序列 1 2 3 能够生成的非负整数为 +1+2+3=6,-1+2+3=4,+1-2+3=2,+1+2-3=0,-1-2+3=0,集合为{0,2,4,6}
数字序列 1 2 3 4 能够生成的非负整数为 +1+2+3+4=10,-1+2+3+4=8,+1-2+3+4=6,+1+2-3+4=4,+1+2+3-4=2,
-1-2+3+4=4,-1+2-3+4=2,-1+2+3-4=0,+1-2-3+4=0,集合为{0,2,4,6,8,10}
由规律可见,对于一个确定的数字序列,其可能的所有结果奇偶性一致,为连续的奇(偶)数。
我们再列出不等式
1+2+3+...+n >= k
可得到 n(n+1)>=2*k
由二次一元方程可解得 n >= 0.5* (sqrt(1+8*k) - 1)
此时,若n满足 n(n+1)/2 与 k的奇偶性一致,这个n就是要的答案。
另外,对于负数k,其结果与它的相反数-k(即正整数)一致。
【代码】
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
int getSquare(int x) { //求得n(n+1)/2的值
int y;
if ( (x&1) == 0) {
y = x>>1;
return y*(x+1);
}
else {
y = (x+1)>>1;
return y*x;
}
}
int main()
{
int k, n, T;
scanf("%d", &T);
for (int t = 1; t <= T; t ++) {
scanf("%d", &k);
if (k < 0) k = -k; //负数转为正数处理
n = (int)((sqrt(8.0*k+1.0)-1.0)/2); //求得不等式1+2+3+...+n>=k中最小的n
int sq = getSquare(n);
while (true) {
if (sq >= k && ((sq&1) == (k&1)) ) //若n(n+1)/2大小超过k,且与k的奇偶性一致,则n为答案
break;
n ++; //若条件不满足,n向上寻找
sq = getSquare(n);
}
if (n > 0)
printf("%d\n", n);
else
printf("3\n"); //n=0特殊处理
if (t < T)
printf("\n");
}
}