说说:这道题初看完全不知道如何下手,但最终也不过就是个二分查找而已,其实不用二分也行,从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