UVa 10025 The ? 1 ? 2 ? ... ? n = k problem

来源:互联网 发布:破解软件网站大全 编辑:程序博客网 时间:2024/06/13 05:11

【解题思路】

若直接用枚举搜索,所遍历的可能性将会超过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中最小的nint 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);elseprintf("3\n"); //n=0特殊处理if (t < T)printf("\n");}}




0 0
原创粉丝点击