The ? 1 ? 2 ? ... ? n = k problem |
The problem
Given the following formula, one can set operators '+' or '-' instead of each '?', in order to obtain a given k
? 1 ? 2 ? ... ? n = k
For example: to obtain k = 12 , the expression to be used will be:
- 1 + 2 + 3 + 4 + 5 + 6 - 7 = 12
with n = 7
The Input
The first line is the number of test cases, followed by a blank line.
Each test case of the input contains integer k (0<=|k|<=1000000000).
Each test case will be separated by a single line.
The Output
For each test case, your program should print the minimal possible n (1<=n) to obtain k with the above formula.
Print a blank line between the outputs for two consecutive test cases.
Sample Input
2 12 -3646397
Sample Output
7 2701
Alex Gevak
September 15, 2000 (Revised 4-10-00, Antonio Sanchez)
题目的意思是说,在从1~n这n个数之间,通过添加+、-号使表达式的值为k,求这样的n最小为多少
通过列举前几个n的值可以组合出的k,很容易发现规律:
n=1 : k=1,-1
n=2 : k=3,-3,1,-1
n=3 : k=6,-6,4,-4,2,-2,0
n=4 : k=10,-10,8,-8,6,-6,4,-4,2,-2,0
n=5 : k=15,-15,13,-13,11,-11,9,-9,7,-7,5,-5,3,-3,1,-1,0
…… ……
可以看出,当(n+1)/2向下取整为奇数时,可以组合出不大于n(n+1)/2的所有奇数
当(n+1)/2向下取整为偶数时,可以组合出不大于n(n+1)/2的所有偶数
按照以上规律写程序求解n即可
WA了3次,第一次发现了把浮点数转化为它向上取整的整数时写的有问题,第二次发现当k=0时需要特殊判断,第三次发现在解二次方程求出的那个表达式中有8*k这个会溢出int的范围,要强制类型转换一下
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 5 using namespace std; 6 7 int main() 8 { 9 int kase; 10 11 scanf("%d",&kase); 12 13 while(kase--) 14 { 15 int k; 16 17 scanf("%d",&k); 18 19 if(k<0) 20 k=-k; 21 22 double temp=(sqrt(8*((long long)k)+1)-1)/2; 23 int n=temp; 24 25 if(fabs(temp-n)>1e-9) 26 n++; 27 28 bool even=(k%2==0); 29 30 if(even) 31 while(((n+1)/2)%2) 32 n++; 33 else 34 while(((n+1)/2)%2==0) 35 n++; 36 37 printf("%d ",k==0?3:n); 38 if(kase) 39 printf(" "); 40 } 41 42 return 0; 43 }