第一题(共四题 100 分):连续正整数( 10 分)
题目描述:一个正整数有可能可以被表示为 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
评分标准:程序输出结果是否正确。
my answer:
思路:1 <= start < end <= n/2+1,start从1开始遍历,end用二分搜索
总结:(1)题目要求从命令行输入,没有仔细阅读题目(2)n用长整型比较好
优化:start不需要一个一个遍历
#include <iostream> using namespace std; int main() { int n, start, end, i, sum; while(cin>>n) { bool flag = 0; start = 1; while(start <= n/2) { int low = start, high = n/2+1, mid; while(high >= low) { mid = (high + low)/2; sum = (start + mid) * (mid - start + 1); if(sum == n * 2) { flag = 1; for(i = start; i <= mid; i++) { if(i != start)cout<<' '; cout<<i; } cout<<endl; break; } else if(sum < n * 2) low = mid + 1; else if(sum > n * 2) high = mid - 1; } start++; } if(!flag)cout<<"NONE"<<endl; } return 0; }
牛A陈世熹的比赛答题源码:
结果可以分为两类,以15为例:
一种是像12345和456这样的,每个序列的个数是奇数个,另这个序列的中间的数为mid,那么n%mid==0&&(n/mid)%2==1
另一种是像78这样的序列,每个序列的个数是偶数个,另这个序列中第一个数+倒数第一个数==第二个数+倒数第二个数==sum,那么sum%2==1&&n%sum==0
#include <iostream> #include <cstdio> #include <utility> #include <algorithm> #include <cmath> using namespace std; int N, M; pair<int, int> List[65536]; int main(int argc, char* args[]) { int I, J, Max, A, B; if (argc <= 1) return 0; sscanf(args[1], "%d", &N); M = 0; Max = (int)sqrt((double)N) * 2; for (I = 2; I <= Max; I++) if (I & 1) { if (N % I == 0) { J = N / I; A = J - I / 2; B = J + I / 2; if (A >= 1) List[M++] = make_pair(A, B); } } else { if (N % I != 0 && N % (I / 2) == 0) { J = N / I; A = J - I / 2 + 1; B = J + I / 2; if (A >= 1) List[M++] = make_pair(A, B); } } if (M == 0) printf("NONE\n"); else { sort(List, List + M); for (I = 0; I < M; I++) { printf("%d", List[I].first); for (J = List[I].first + 1; J <= List[I].second; J++) printf(" %d", J); printf("\n"); } } return 0; }
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> using namespace std; #define _MAXL 2000000 void GetN(char *s,long long &N) { N=0; for (int i=0;s[i];i++) N=N*10+(s[i]-48); } void print_bigint(long long n) { if (n>=10) print_bigint(n/10); printf("%d",int(n%10)); } void Solve(long long N) { bool find_answer=false; long long L,T,A1,k; for (L=2;L<=_MAXL && L*(L-1)/2<N;L++); for (L--;L>=2;L--) { T=L*(L-1)/2; if (N>T && (N-T)%L==0) { find_answer=true; A1=(N-T)/L; for (k=0;k<L;k++) { if (k>0) printf(" "); print_bigint(A1+k); } printf("\n"); } } if (!find_answer) printf("NONE\n"); } int main(int argc,char *arg[]) { long long N; GetN(arg[1],N); Solve(N); return 0; }