我第一个思路是直接暴力去求解的:
就是设置一个窗口然后去滑动。这个时间复杂度可以说最坏是O(n^2)
不过吧,就是超时了。。。我在想有什么判断可以让程序提前判断退出的,但是这改变不了程序的时间复杂度说实话~
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n;
ll L;
ll minLen=0x3f3f3f3f;
ll res;
int main()
{
cin>>n>>L;
ll start=0,end=1;
ll nowLen=0;
bool find=false;
while(start<n && end<n && start<=end)
{
nowLen=end-start+1;
ll sum=(start+end)*nowLen/2;
//和等于n 且长度大于等于L
//长度若小于最小长度则记录
if(sum==n && nowLen>=L && nowLen<minLen)
{
minLen=nowLen;
res=start++;
find=true;
}
else if(sum<n) end++;
else start++;
}
if(!find||minLen>100) cout<<"No";
else
{
int i=res;
for(;i<res+minLen-1;++i) cout<<i<<" ";
cout<<i;
}
return 0;
}
我在vs上边跑了一下,像这样:
牛客网上边:
然后看到直接用求和公式推导的,挺巧妙的。
思路就是等差数列求和:
这样我们逆推出来a1的公式,然后遍历一遍长度n就好了,这样的时间复杂度是O(1)
#include <iostream>
using namespace std;
int main(){
int n,l;
cin>>n>>l;
for(int i = l;i<=100;i++){
if((2*n+i-i*i)%(2*i)==0){
int temp = (2*n+i-i*i)/(2*i);
if(temp<0) continue;
for(int j = 0;j<i;j++){
cout<<temp++<<" ";
}
return 0;
}
}
cout<<"No"<<endl;
return 0;
}
这提示我们利用数学从另外的角度看问题,谢谢大佬教我编程~