题意:两个操作,一个是给序列任意位置+1,一个是赋值某一个元素加到后面。问你最少多少步和能>=n。
思路:贪心
贪心策略:先自增到某个数x,然后赋值这个x若干次直到超过n。
所以只需要枚举[1,sqrt(n)]之间的因数,枚举x作比较即可。
贪心策略的证明:假设现在我们经过a-1次操作,构造出了一个a,那么我们现在想得到一个b,设(b>a),所以我们现在需要1+(b-a)次变化,可以得到数列:ab(先复制一次a,然后将那个复制的a操作b-a次变成b)
那么如果我直接将a操作b-a次变成b,然后再复制一次b,那么我们在同样进行1+(b-a)次操作的情况下,可以得到数列:bb>ab,说明这个策略能够更快的实现>=n。
所以说:最终的数列最优的情况是所有位置的数均相同的。
#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
#define int long long
int t;
int n;
signed main()
{
cin.tie(0),ios::sync_with_stdio(false);
cin>>t;
while(t--)
{
cin>>n;
int m=sqrt(n*1.0);
int ans=inf;
for(int i=1;i<=m;++i)
{
int t1=i-1;
double tmp=1.0*(n-i)/i;
int t2=(int)tmp;
if((tmp-t2)>0) t2+=1;
ans=min(ans,t1+t2);
}
cout<<ans<<endl;
}
return 0;
}
思路参考了两位博主:
待到山花烂漫时
Codeforces Round #674 (Div. 3)