题解

2 条题解

  • 1
    @ 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;
    }
    
    
    • @ 2017-11-01 17:45:19

      比赛期间禁止看题解!!!

  • 0
    @ 2017-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%
上传者