题目大意:
若连续加数的和为m(10≤m≤2,000,000),输出首项和末项。
思路一:暴力
直接枚举首项,然后向后遍历,直到大于或等于m就停止遍历,如果和与m相等,输出即可。
时间复杂度:O(m^2)
理想得分:50分。实际得分:100分(数据太水了)
#include<bits/stdc++.h>
using namespace std;
int m;
int main(){
cin>>m;
for(int i=1;i<m;i++){
long long sum=0;//记录总和
int prev=i;//加数
while(sum<m){
sum+=prev;
prev++;
}
if(sum==m){
cout<<i<<" "<<prev-1<<"\n";
}
}
return 0;
}
思路二(正解):数学
连续加数组成的序列其实就是一个等差数列,我们不妨假设这个等差数列的末项为x,序列长度为i,可以求出此序列的和为:(x-i+1+x)*i/2=m -> 2*x*i+(i-1)*i=2*m -> x=(2*m-(i-1)*i)/(2*i)
所以选择枚举序列长度,求出末项。
由于此数列的长度最多为sqrt(2*m)(从1加到x),则时间复杂度为O(sqrt(2*m))
#include<bits/stdc++.h>
using namespace std;
int m;
int main(){
cin>>m;
for(int i=sqrt(2*m);i>=2;i--){
if((2*m-i*(i-1))%(2*i)==0){
cout<<(2*m-i*(i-1))/(i*2)<<" "<<(2*m-i*(i-1))/(i*2)+i-1<<"\n";
}
}
return 0;
}