http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=966
对于k<0,可以将加号变为减号,减号变为加号,这样和原问题是等价的,所以只需要考虑k>=0的情况。
可以证明这样一个结论:对于任意x in [1, n*(n+1)/2],可以用1...n这n个数的若干个数的和构成。
这样对与k>=0,题目就化为了求最小的 n 满足 n*(n+1)/2>= k,即min{n|n*(n+1)>=k},显然复杂度过得去。
特别要注意题目要求每两个输出之间有一个空行。
# include <stdio.h> # include <math.h> int ic; int M; int main() { scanf("%d", &ic); for (int i = 0; i < ic; ++i) { if (i) printf("\n"); scanf("%d", &M); if (M < 0) M = -M; /* 这个递增的方法是看到的,虽然这道题复杂度要求不高,这个方法的复杂度略高,特别是如果样例在10^5以上 for (int n = 1; ; ++n) { long long int N = n*(n+1)/2; if (N >= M && N%2 == M%2) { printf("%d\n", n); break; } } */ // 这个复杂度在O(1)级别 int n = (int)floor(sqrt(M*2.0)*0.5-0.5) - 1; long long int N = 0; while (n <= 0) ++n; while (1) { N = ((long long int)n)*(n+1)/2; if (N >= M && N%2==M%2) { printf("%d\n", n); break; } ++n; } } return 0; }