数列(sequence)

数 列 ( s e q u e n c e ) 数列(sequence) sequence

题目链接:jzoj 2752

题目

把一个正整数分成一列连续的正整数之和。这个数列必须包含至少两个正整数。你需要求出这个数列的最小长度。如果这个数列不存在则输出 − 1 -1 1

输入

每行包含一个正整数 n n n
每个文件包含多行,读入直到文件结束。

输出

对于每个 n n n,输出一行,为这个数列的最小长度。

输入样例

9
2

输出样例

2
-1

数据范围

对于所有数据, n ≤ 2 63 n≤2^{63} n263

思路

一道思维题。

首先,我们可以知道,当 n n n 1 1 1 2 2 2的时候,答案是 − 1 -1 1
然后,我们可以通过观察数据与打表发现,当 n n n为奇数的时候(除了 1 1 1),答案都为 2 2 2
接着,我们再来处理 n n n为偶数的情况,可以分两种情况讨论:

  1. 数列的长度为偶数,则数列的平均值是一个小数( ∗ ∗ ∗ . 5 ***.5 .5的样子)。而我们要让这个数列的数尽可能少,这个数列的和有不变,就只能让数列的平均值尽可能的大。我们可以找出 n n n最大的奇数因子,而长度就为: n   /   最 大 的 奇 数 因 子   ∗   2 n\ /\ 最大的奇数因子\ *\ 2 n /   2
  2. 数列的长度为奇数,那么数列的平均值就是一个整数,我们只要直接枚举长度,找到最小的奇数长度就可以了。

然后那个小答案就是那个,若是两个都没有答案就输出 − 1 -1 1

代码

#include<cstdio>
#define rr register
#define ll long long

using namespace std;

ll n;

int main() {
	while (scanf("%lld", &n) == 1) {//读入
		if (n < 3) {//n为1或者2的话都是-1
			printf("-1\n");
			continue;
		}
		if (n % 2 == 1) {//其它的如果是奇数答案都为2
			printf("2\n");
			continue;
		}
		
		ll nn = n, ans = 100000000000000;
		while (nn % 2 == 0) nn >>= 1;//求出这个数的最大奇数因子
		
		if ((nn + 1) / 2 - n / nn >= 0) {//求出偶数长度中最小的长度
			ans = n / nn * 2;
			if ((nn + 1) / 2 - n / nn == 0)
				ans--;
		}
		for (rr ll int i = 3; i <= ans && i * i <= n && i <= nn; i += 2)//找出有没有奇数长度更小的
			if (n % i == 0) {
				ans = i;
				break;
			}
		
		if (ans == 100000000000000) printf("-1\n");//没有找到序列
			else printf("%lld\n", ans);//输出
	}
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值