说说:这道题初看完全不知道如何下手,但最终也不过就是个二分查找而已,其实不用二分也行,从1开始遍历从显示的结果来看花费的时间是一样的。首先,讨论N是正数的情况。很明显这是个等差数列求和的问题,当总和任然小于N的时候,那么显然此时的n还不够大。当然若直接等于N了,那输出答案就好了。如果最后总和大于N了,但两者之差为奇数,这显然是不行的,因为把序列中任何一个数变为其相反数,那总和都相当于减去一个偶数。所以此时n需要进一步变大,直到两者的差为偶数。最后将序列中的某些正号变为负号,不过具体的我们不用管,问题就解决啦!
题目:
Given the following formula, one can set operators ‘+‘ or ‘-‘ instead of each ‘?‘, in order to obtain a given k
给定以下公式,你为了获得要求的K可以填入‘+’或‘-’代替每个‘?’
? 1 ? 2 ? ... ? n = k
For example: to obtain k = 12 , the expression to be used will be:
比如:为获得k=12.表达式如下:
- 1 + 2 + 3 + 4 + 5 + 6 - 7 = 12
with n = 7
其中n=7
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).
每个测试包含了一个整数k (0<=|k|<=1000000000).
Each test case will be separated by a single line.
每组测试会用一个空行隔开
For each test case, your program should print the minimal possible n (1<=n) to obtain k with the above formula.
对于每组测试,你的程序需要给出最小的n(1<=n)按上述公式去获得k
Print a blank line between the outputs for two consecutive test cases.
连续的两组测试数据的输出之间输出一空行
2 12 -3646397
7 2701
源代码:
#include <stdio.h>
#include <math.h>
int main(){
int left,right,mid;
int N,n;
//freopen("data.txt","r",stdin);
scanf("%d",&n);
while(n--){
left=1;
right=(int)sqrt(2000000000);
scanf("%d",&N);
N=N<0?-N:N;
while(left<=right){//二分查找
mid=(left+right)/2;
if((mid+1)*mid/2==N)
break;
else if((mid+1)*mid/2<N)
left=mid+1;
else
right=mid-1;
}
if((mid+1)*mid/2==N){//找到则直接输出
printf("%d\n",mid);
if(n) printf("\n");
continue;
}
else if((mid+1)*mid/2<N)
mid++;//保证序列的和大于N
if(((mid+1)*mid/2-N)%2)//若序列和减去N为奇数,则须使该值变为偶数
if(mid%2)//当前的最大值为奇数则需加2
mid+=2;
else
mid++;
printf("%d\n",mid);
if(n) printf("\n");
}
return 0;
}The ? 1 ? 2 ? ... ? n = k problem UVA 10025,布布扣,bubuko.com
The ? 1 ? 2 ? ... ? n = k problem UVA 10025
原文地址:http://blog.csdn.net/u011915301/article/details/38406297