应用题_将一数字分解连续整数和
<<<百度编程竞赛题目??>>>
题目描述:一个正整数有可能可以被表示为n(n>=2)个连续正整数之和,如:
15=1+2+3+4+5
15=4+5+6
15=7+8
请编写程序,根据输入的任何一个正整数,找出符合这种要求的所有连续正整数序列。
输入数据:一个正整数,以命令行参数的形式提供给程序。
输出数据:在标准输出上打印出符合题目描述的全部正整数序列,
每行一个序列,每个序列都从该序列的最小正整数开始、以从小到大的顺序打印。
如果结果有多个序列,按各序列的最小正整数的大小从小到大打印各序列。
此外,序列不允许重复,序列内的整数用一个空格分隔。
如果没有符合要求的序列,输出“NONE”。
例如,
对于15,其输出结果是:
1 2 3 4 5
4 5 6
7 8
对于16,其输出结果是:
NONE
评分标准:程序输出结果是否正确。
算法分析
设可行数列为 A = { a1 , a2 , a3 , ... }
根据题意知,A 是一组 d=1 的等差序列,
没 A 有 s 个元素,
则数列和 SA = s * a1 + s(s-1)/2 = n
显然 a1 的取值范围为 ( 1<=a1<=n/2 )
问题就是成了判断一元二次方程有无整数解,
其中 a1 , n 为常数,s 为所求变量。
s = ( -(2*a1-1) + sqrt( (2*a1-1)^2 + 8*n ) ) / 2
// 源程序
// pro.cpp : 定义控制台应用程序的入口点。
// 10:13 2005-10-22
//
#include "stdafx.h"
#include "math.h"
#include "conio.h"
bool findSeq( unsigned int n )
{
bool flag = false;
unsigned int a1;
unsigned int half = n / 2;
for( a1 = 1 ; a1 <= half ; a1++ )
{
double s = 0;
s = 4 * a1 * a1 - 4 * a1 + 1 + 8 * n;
s = sqrt( s );
s = s + (-2) * (double)a1 + 1;
s /= 2;
unsigned int t = s;
if( fabs( s - (double)t ) < 1e-6 )
{
flag = true;
for( int i = 0 ; i < t ; i++ )
printf( "%3d" , a1+i );
printf( "/n" );
}
}
if( !flag )
printf( "NONE/n" );
return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
findSeq( 16 );
getch();
return 0;
}