51nod 1837 砝码称重


原地址:http://blog.csdn.net/qq_28954601/article/details/78151199

最坏情况就是每次称量的结果都和把  ai  当作  i  称量的结果相同,所以只用考虑在这种情况下要多少次称量才能称量出至少一定有一个  ai=i  。

显然答案不会超过  3  ,因为高斯证明过任意一个正整数可以表示成三个三角形数的和。

实际上答案最大是  2  ,通过观察或模拟,我们可以得到以下结论:

  • 当  n  是三角形数时(即  n=k(k+1)2  ),只需一次,称量  1+2++k=n  是否成立,因为任选  k  个砝码能组成的最小质量和是  n  。
  • 当  n  是三角形数  +1  时(即  n=k(k+1)2+1  ),只需一次,称量  1+2++k<n  是否成立,原因类似于上一个结论。
  • 当第  n  个三角形数是平方数时(即  n(n+1)2=k2  ),只需一次,称量  1+2++(k1)=(k+1)+(k+2)++n  是否成立,因为去掉一个砝码后能够拆分成两个质量和相同的砝码区间只有一种方案。
  • 当第  n  个三角形数是平方数  +1  时(即  n(n+1)2=k2+1  ),只需一次,称量  1+2++(k1)<(k+1)+(k+2)++n  是否成立,原因类似上一个结论。
  • 其他情况,不难证明  n,n1,n2  之中至少有一个数可以表示成两个三角形数的和,从而只需要称两次,因为小于号可以使用至多两次。

判断一个数是不是平方数只需要将其开根下取整再平方进行检验,判断三角形数同理。

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>

using namespace std;
typedef long long ll;
const int MAXN = 1000010;
const int INF = 1000000000;
int _w;

int a[MAXN], sz;
void prelude() {
	int s = 1;
	for( int i = 2; s < INF; s += i, ++i )
		a[sz++] = s, a[sz++] = s+1;
	sort(a, a+sz);
	sz = int(unique(a, a+sz) - a);
}

int main() {
	int n;
	prelude();
	while( scanf( "%d", &n ) != -1 ) {
		if( n == 1 ) puts("0");
		else if( *lower_bound(a, a+sz, n) == n ) puts("1");
		else {
			ll t = (ll)n*(n+1)/2;
			ll sq = ll(sqrt(t) + 0.5);
			puts( sq*sq == t || sq*sq+1 == t ? "1" : "2" );
		}
	}
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值