2 条题解
-
1chrB LV 8 MOD @ 2017-11-01 17:15:13
贪心,每次最后多出的去随便加掉。代码比较难看,自己举个例子。
#include<bits/stdc++.h> using namespace std; typedef unsigned long long ll; int main(){ ll n,s=0,g=1,ans=0; scanf("%llu",&n); while(!(n&1)){ n>>=1; g<<=1; ans+=n*g; } while(n){ if(s<g){s=s+g;if(s!=g)ans+=s;--n;} if(n&1){s=s+g;ans+=s;--n;} ans+=(n/2)*(g<<1); g<<=1; n>>=1; } printf("%llu\n",ans); return 0; }
-
02017-11-04 18:26:37@
先MOBY上面大佬,注释写的应该比较清楚了get√
cpp
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
ull ans=0;
ull branch(ull x){
if(x==1)return 0;
if(x%2)return branch(x/2)*2+x+(ull)floor(log10(x)/log10(2))+1;
return branch(x/2)*2+x;
}
int main(){
//设将n堆石子合并的最小体力值消耗=f(n)
//易证f(n)=f(n/2)+f((n+1)/2)+n,递归边界f(1)=0,时间复杂度(log n)
//但是如果纯递归这道题每一次递归会调用两次函数,x在不断/2,而调用次数也在×2,所以总的时间复杂度还是O(n)
//所以要优化,当n为偶数时,我们计算一次n的值,再×2就好了
//当n为奇数时,此题就变成了求f(n)与f(n+1)的关系,可以发现这两者在递归时总是有一部分是相同的,不同那一部分可以单独递归,这样拆到最后就成了常数的差,每一次不同部分的递归会让f(n+1)的常数比f(n)的常数多1,一共可以分log(n)次,又因为开始阶段常数就多1,所以f(n+1)=f(n)+log2(n+1)+1;
//时间复杂度就这样成功变成了O(log2 n)
ull n;
scanf("%lld",&n);
printf("%lld",branch(n));
return 0;
}
- 1
信息
- 难度
- 7
- 分类
- (无)
- 标签
- (无)
- 递交数
- 16
- 已通过
- 7
- 通过率
- 44%
- 上传者