sgu 178

f(n)表示问题的解 

第一步:将n0 = n分成三部分a1 ,b1= 1, n1;其中a1 = n0 - n1 - 1,a1 〉=  n1;

n1 是之后要分解的 ,可行解为 f(n1)

我们得到  a1,b1, f(n1)

  • 前n1天,用n1(会拆开)支付,解为f(n1)
  • 第n1+1天用 b1支付
  • 第n1+2天用a1(完整的)支付,必须找零a1 - 1,店主有n1+1个,所以必须有 a1-1 < = n1+1

综上: n1 =  floor(n0/2) - 1; 

....... 

第(k+1)步:这一步求 f(nk)

分解nk 为 a(k+10, b=1, n(k+1),其中a(k+1) = nk - 1 - n(k+1),a(k+1) 〉= n(k+1)

n(k+ 1) 是之后要分解的 ,可行解为 f(n(k+1))

得到的是 a1, a2 ..........ak, a(k+1),  (k+1)个1, f(n(k+1))

  • 前n(k+1)天,用f(n(k+1))支付
  • 之后的k+1天用所有的1支付
  • 之后必须用a(k+1)支付, 找零 a(k+1) - 1, 店主又n(k+1)+ k + 1 个,所以 a(k+1)-1 <= n(k+1)+k+1

n(k+1) 越小越好

n(k+1) = floor((nk-k-2)/2) 

终止条件:第k步中分解nk时, 如果nk -k <= 1

因为k可以表示1的个数,满足条件说明不需要分解nk了。 

举例:n=147,    

kabnk
0  147
174172
237134
318115
4915

 解:74, 37, 18, 9, 5, 1, 1, 1, 1

 ==========================================

 #include <stdio.h>

long long n;
int k = 0; //!< how many ones we have; which step we are in.

int main()
{
  scanf("%lld", &n);
  while (n - k > 1) {
    n = (n - k - 2) >> 1;
    ++k;
  }

  printf("%d\n", k);
  return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值