巧克力棒

巧克力棒(chocolate)
Time Limit:1000ms Memory Limit:64MB
【题目描述】
LYK 找到了一根巧克力棒,但是这根巧克力棒太长了,LYK 无法一口吞进去。具体地,这根巧克力棒长为 n,它想将这根巧克力棒折成 n 段长为 1 的巧克力棒,然后慢慢享用。它打算每次将一根长为 k 的巧克力棒折成两段长为 a 和 b 的巧克力棒,此时若 a=b,则LYK 觉得它完成了一件非常困难的事,并会得到 1 点成就感。LYK 想知道一根长度为 n 的巧克力棒能使它得到最多几点成就感。
【输入格式】(chocolate.in)
  第一行一个数 n。
【输出格式】(chocolate.out)
  一个数表示答案。
【输入样例】
  7
【输出样例】
  4
【数据范围】
  对于 20%的数据 n<=5。
  对于 50%的数据 n<=20。
  对于 80%的数据 n<=2000。
  对于 100%的数据 n<=1000000000。
【样例解释】
  将 7 掰成 3+4, 将 3 掰成 1+2, 将 4 掰成 2+2 获得 1 点成就感, 将剩下的所有 2 掰成 1+1获得 3 点成就感。总共 4 点成就感。

【题目分析】

  可以发现,如果巧克力棒的长度为2^x的话,那他将获得2^x-1点成就感(这个很容易证明,因为你每一次折都会增加成就感,需要折2^x-1次)。那么问题来了,如果他给出的长度不恰好为2^x怎么办,因为问题是要求出最大成就感,那我们就找到最大的x使得2^x刚好小于或等于给出的这个长度(刚好就是说2^(x+1)就会大于长度),然后继续找出剩下的那段的最大加到答案里,就不停找不停找....复杂度的话我算不出来,总之不会超时

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int a[35];
int ans;
int n;
int solve(int pos,int s)
{
    int i;
    if(s==1||s==0) return 0;
    for(i=pos;i>=0;i--)
        if(s>=a[i])
            break;
    return a[i]-1+solve(i,s-a[i]);
}

int main()
{
    freopen("chocolate.in","r",stdin);
    freopen("chocolate.out","w",stdout);
    a[0]=1;
    for(int i=1;i<=30;i++)
        a[i]=a[i-1]*2;
    scanf("%d",&n);
    int xx=1;
    for(int i=0;i<=n;i++)
    {
        if(xx>=n)
        {
            ans=solve(i,n);
            break;
        }
        xx*=2;
    }
    printf("%d",ans);
    fclose(stdin);fclose(stdout);
}
原文地址:https://www.cnblogs.com/xiaoningmeng/p/6039004.html