數列(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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章