巧克力棒(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); }