【题解】连续数和

【题目描述】

一个正整数有可能可以被表示为n(109>=n>=2)个连续正整数之和,如:

15 = 1 + 2 + 3 + 4 + 5 15 = 4 + 5 + 6 15 = 7 + 8 \begin{aligned}&15=1+2+3+4+5 \\ &15=4+5+6 \\ &15=7+8\end{aligned} 15=1+2+3+4+515=4+5+615=7+8

根据输入的任何一个正整数,找出符合这种要求的所有连续正整数序列。

【输入格式】

一个正整数 N N N

【输出格式】

输出符合题目描述的全部正整数序列,每行一个序列,每个序列都从该序列的最小正整数开始、以从小到大的顺序打印。如果结果有多个序列,按各序列的最小正整数的大小从小到大打印各序列。此外,序列不允许重复,序列内的整数用一个空格分隔。如果没有符合要求的序列,输出 “NONE” 。

【样例输入输出1】

样例输入:(num.in)

15

样例输出:(num.out)

1 2 3 4 5
4 5 6
7 8

【样例输入输出2】

样例输入:(num.in)

16

样例输出:(num.out)

NONE

【数据规模与约定】

时间限制: 1 s 1 \text {s} 1s

空间限制: 256 MB 256 \text {MB} 256MB
【解析】
显然,输出的是一个等差数列,公差为1。
那么我们设它的首项为 a a a ,项数为 k k k ,则这个数列的末项为 a + k − 1 a+k-1 a+k1
根据题意可得, ( a + a + k − 1 ) × k 2 = n \frac{(a+a+k-1)\times k} {2}=n 2(a+a+k1)×k=n移项得, 2 a k + k ( k − 1 ) = 2 n 2ak+k(k-1)=2n 2ak+k(k1)=2n整理得, a = 2 n − k ( k − 1 ) 2 k a=\frac{2n-k(k-1)}{2k} a=2k2nk(k1)
如此一来,我们可以知道, ( 2 n − k ( k − 1 ) ) ∣ 2 k (2n-k(k-1))|2k (2nk(k1))2k,且 a > 0 a>0 a>0 ,因此,我们只要枚举 k k k 就好了,那么它的范围是多少呢?
刚才说了, a a a 是大于 0 0 0 的,而 k k k 又是正整数,所以, 2 n − k ( k − 1 ) > 0 2n-k(k-1)>0 2nk(k1)>0 k 2 + k < 2 n k^2+k<2n k2+k<2n k 2 必 然 是 小 于 2 n 的 k^2 必然是小于 2n的 k22n
接下来的就不用多说了,直接上代码吧ヽ( ̄▽ ̄)ノ当然,如果无解不要忘记输出 NONE !
【代码展示】

#include
#define ud using namespace std
#define itn int
#define ll long long
ud;
int n;
bool flag=0;
inline long long read()
{
	long long sum=0,flag=1;
	char c;
	for(;c<'0'||c>'9';c=getchar())if(c=='-') flag=-1;
	for(;c>='0'&&c<='9';c=getchar())sum=(sum<<1)+(sum<<3)+c-'0';
	return sum*flag;
}
int main()
{
	n=read();
	for(int k=sqrt(2*n);k>=2;--k)
	{
		if((2*n-k*(k-1))%(2*k)==0)
		{
			int a=(2*n-k*(k-1))/(2*k);
			printf("%d",a);
			for(int j=a+1;j<=a+k-1;++j)
			printf(" %d",j);
			printf("\n");
			flag=1;
		}
	}
	if(!flag)
	printf("NONE\n");
	return 0;
}

你可能感兴趣的:(数论专题)