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

【解题思路】

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

		if (t < T)
			printf("\n");
	}
	
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值