数列(sequence)

sequence数列(sequence)

题目链接:jzoj 2752

题目

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

输入

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

输出

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

输入样例

9
2

输出样例

2
-1

数据范围

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

思路

一道思维题。

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

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

然后那个小答案就是那个,若是两个都没有答案就输出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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章