原题链接
题的大意是:给定一个数列1、2、3、·········、N,找出所有符合条件的子数列,即子数列的各项之和等于M,,输入的测试用例有多组,输入N空格M,将符合的子数列按照 [p,q] 的格式输出。每个测试用例后面都跟一个空行。
第一次得到这种题,首先想到的就是最笨的办法:一个一个找,反正也不是自己算。于是很容易就有了代码:
# include
int main (){
int m,n,i,j,s;
while (~scanf ("%d%d",&m,&n),n!=0 && m!=0){
for (i=1;i<=n;i++){
s=0;
for (j=i;j<=n;j++){
s=s+j;
if (s>=n){
if (s==n){
printf ("[%d,%d]\n",i,j);
}
break;
}
}
}
printf ("\n");
}
}
虽然嵌套的层数比较多,但是很容易理解。提交的时候,出现了(Time Limit Exceeded)这样的判断,也就是超时了,说明这个算法不行。
那怎么解决这个问题呢?
第一:先进行长度x上限的判断,代码如下:
for (i=1,s=0;s<=n;i++){//···n代表输入的M(所求的和)
s+=i;
}
x=i-1;//··············x代表长度
x最后减去了一是因为,经过for循环之后s肯定大于M,所以x减一,可以减少算数的步骤。
第二:筛选出符合要求的子数列;代码如下:
for (i=x;i>=2;i--){//······让长度依次递减
if (n%i==0){//·········如果平均数是整数
p=n/i-i/2;
q=n/i+i/2;//·········计算开始点和结束点(格式:[p,q])
}
else if (2*n%i==0){//·········如果平均数乘上2是整数
p=n/i-i/2+1;
q=n/i+i/2;//·········计算开始点和结束点(格式:[p,q])
}
else{
continue;
}
t=(q-p+1)*(p+q)/2;//计算得到的数列的各元素之和,用于检验是否符合条件
if (t==n && p>0){
printf ("[%d,%d]\n",p,q);
}//·······如果检验成功就按格式输出
}
最后进行整理:
# include
int main (){
int m,n,i,s,x,p,q,t;
while (~scanf ("%d%d",&m,&n),m!=0 || n!=0){
for (i=1,s=0;s<=n;i++){
s+=i;
}
x=i-1;
for (i=x;i>=2;i--){
if (n%i==0){
p=n/i-i/2;
q=n/i+i/2;
}
else if (2*n%i==0){
p=n/i-i/2+1;
q=n/i+i/2;
}
else{
continue;
}
t=(q-p+1)*(p+q)/2;
if (t==n && p>0){
printf ("[%d,%d]\n",p,q);
}
}
printf ("[%d,%d]\n\n",n,n);//···输出本身的那一种情况
}
return 0;
}
如果有兴趣,期望能和大家一起交流。
这是我第一次发表文章,还望各位大神多多包涵!!!