您的位置:首页 > 其它

2005年百度之星预赛第一题

2011-06-03 11:18 204 查看
题目描述:一个正整数有可能可以被表示为 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

评分标准:程序输出结果是否正确。

解法一:最简单的想法,双重for循环。伪代码:

for(int i=1; i < n/2; i ++)
int sum =0;
for(int j=i; j < n/2; j ++)
sum += j;
if(sum > n)
break;
else if(sum == n)
print();


时间复杂度o(n^2).

解法二:确定a1以后,我们知道只要确定ap就可以利用通项公式(a1 + ap) * (ap – a1 +1)
/ 2求和.那么为了确定ap,可以采用二分查找法的方式。伪代码:

for(int i=1; i < n/2; i ++)
{
int start = i; end = n/2;
int mid = 0;
while(start <= end)
{
mid = (start + end)/2;
sum = (i + mid) * (mid – i +1) / 2;
if(sum > n)
end = mid -1;
else if(sum < n)
start = mid +1;
else
print();
}
}


时间复杂度为o(nlog(n))

解法三:sum = (a1 + ap) * (ap – a1
+1) / 2 = ( a1 + ap) / 2 * (ap – a1
+1) = ak * m 。其中ak表示这个等差数列中间那个数,m表示个数而已。因此只要确定了中间那个数就可以了。

中间数的可能性有两个,一个就是a1, a2, …… ap为奇数个,则中间那个数就是ak。若为偶数,则中间那个数为ak,ak+1。伪代码:
//i=1 可以提高到sqrt(n/2),大家可以去验证一下,但是速度好像不怎么提高
for(int i=sqrt(n/2); i < n/2; i ++)
{
if(n % i == 0)
{
int m = n / i;
if(i > m/2 && m&1==1) //必须为奇数
{
print();
}
}
else if(n %( i + i +1) == 0)
{
int m = n / (i+i+1);
if(i>=m)
print();
}
}

时间复杂度为o(n)。
解法一源代码如下:
#include <iostream>
#include <Windows.h>
#include <fstream>
using namespace std ;
ifstream fin("baidu0501.in");
ofstream fout("baidu0501.out");
int index =1;
int cas;
void search()
{
long long n;
long long sum=0;  //累加
long long flag=0,tag=0;
long t_s = GetTickCount();
fin >> n;
tag = 0;
for(int i=1;i<=n/2;i++)
{
//////////////////////
flag=0;sum=0;//清零,很重要
for(int j=i;j<=n/2+1;j++)
{
sum+=j;
if(sum==n)
{
flag=1; tag=1;
for(int k=i;k<=j;k++)
{fout<<k<<" ";}
}
if (sum > n)
{
break;
}
}
//////////////////////
if(flag==1)
{
fout<<endl;
}
//////////////////////
}
if(tag==0)
{
fout<<"NONE"<<endl;
}
long t_e = GetTickCount();
fout <<"Time:" << t_e- t_s << endl;
}
void main()
{
fin >> cas;
while (index <= cas)
{
search();
index ++;
}
}

解法二源代码如下:
#include <iostream>
#include <fstream>
#include <Windows.h>
#include <math.h>
#include <stdlib.h>
using namespace std;
ifstream fin("baidu0501.in");
ofstream fout("baidu0501.out");
int cas;
int index = 1;
long long n;
bool flag;
void print(int s, int e)
{
for (int i=s; i <= e; i ++)
{
fout << i << " ";
}
fout << endl;
}
//二分法求解
void bisearch()
{
long long half = (n>>1) + 1;
long long start, end, mid;
long long sum;
n = n << 1;
for (long long i=1;  i < half; i ++ )
{
start = i +1;
end = half;
mid = (start + end) >> 1;
while (start <= end)
{
sum = ((i + mid) * (mid - i + 1));
if (sum > n)
{
end = mid -1;
}
else if(sum < n)
start = mid + 1;
else
{
flag = true;
for (long long k=i; k <= mid; k ++)
{
fout << k << " ";
}
fout << endl;
break;
}
mid = (start + end) >> 1;
}
}
}
int main()
{
fin >> cas;
while (index <= cas)
{
long s_t = GetTickCount();
flag = false;
fin >> n;
fout << "Case " << index << ":" << endl;
bisearch();
if (!flag)
{
fout <<"NONE" << endl;
}
index ++;
long s_e = GetTickCount();
fout << "Time:" << s_e - s_t << endl;
}
return 0;
}

解法三源代码如下:
#include<iostream>
#include<fstream>
#include <Windows.h>
#include <math.h>
using namespace std;

ifstream fin("baidu0501.in");
ofstream fout("baidu0501.out");
int cas, index = 1;
int n;
void center()
{
long t_s = GetTickCount();
fout << "Case "<<index <<":" << endl;
int half = n >> 1;
bool flag = false;
for (int i=sqrt((float)half); i <= half; i ++)
{
if (n % i == 0)
{
int m = n / i;
if ( m&1==1 && i >= (m>>1) )
{
int l = i+(m>>1);
for (int j = i-(m>>1); j <= l; j ++)
{
fout << j << " ";
}
fout << endl;
flag = true;
}
}
else if (n % (i + i +1) == 0)
{
int m=n /  (i + i +1);
if ( i >= m)
{
int l = i + m;
for (int j =i-m+1; j <=l; j++ )
{
fout << j << " ";
}
fout << endl;
flag = true;
}//end if i
}//end else
}
if (!flag)
{
fout <<"NONE" << endl;
}
long t_e = GetTickCount();
fout<<"Time : " << t_e - t_s << endl;
}
int main()
{
fin >> cas;
while(index <= cas)
{
fin >> n;
center();
index ++;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: