【数论】【JZOJ】2752数列(sequence)

哎呀,在输入这里卡了好久QWQ


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

Input

每行包含一个正整数n。

每个文件包含多行,读入直到文件结束。

Output

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


思路

对于每个n
·当它是奇数且不为1,答案是2
·当它是偶数我们可以考虑一下两种情况:

  1. 可以分成偶数个连续的数的和
    连续数的平均数的两倍会等于一个奇数,且这个奇数被n整除。要使连续数的个数尽可能少,那么这个奇数要尽可能大。就找到n的最大奇因子。那么,连续数的个数 = n/这个奇因子*2;
  2. 可以分成奇数个连续的数的和
    直接枚举连续的数的数量,从3枚举到n的最大奇因数;

注意判断出现负整数的情况


code

#include<cstdio>
using namespace std;
long long n;
int main(){
	while(scanf("%lld",&n) == 1){
		if(n < 3) printf("-1\n");
		if(n % 2 == 1) printf("2\n");
		else{
			long long k = n,lans = 10000000000000;
			while(k%2==0) k >>=1; 
			if((k+1)/2-n/k >= 0) 
				lans = n/k*2;
			if((k+1)/2-n/k == 0) lans--;
			for(long long i = 3; i <= k && i*i <= n && i <= lans; i+=2)
			  if(n%i==0){
			  	  lans = i;
			  	  break;
			  }
			if(lans == 10000000000000) printf("-1\n");
			else printf("%lld\n",lans);
		} 
	}
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值