• Codeforces 760B:Frodo and pillows(二分)


    http://codeforces.com/problemset/problem/760/B

    题意:有n张床m个枕头,每张床可以有多个枕头,但是相邻的床的枕头数相差不能超过1,问第k张床最多能拥有的枕头数是多少。每张床至少有一个枕头。

    思路:因为每张床至少需要一个枕头,所以先将m减掉n之后来考虑剩余枕头如何分配。

    我们考虑一个最优的情况,假设有5张床,9个枕头,k为3的时候,那么这样分配:1 2 3 2 1,这样其实就如同阶梯一样,要让第k个最高,然后向两边递减。

    我们可以二分答案,使用等差数列的公式来做,数出分配在k左边需要的枕头数,还有k右边需要分配的枕头数,然后判断剩余的枕头数是否满足需要分配的枕头数。

    有一些细节需要考虑:例如上面这个样例,当我们枚举分配给k的枕头数为1的时候,是这样分配的:0 0 1 0 0。即枚举的枕头数比左边(或者右边)的床数要少,这个时候要特殊考虑一下。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define N 3010
     4 #define INF 0x3f3f3f3f
     5 typedef long long LL;
     6 
     7 LL cal(LL a, LL n) { // 等差求和公式
     8     return a * n + n * (n - 1) / 2;
     9 }
    10 
    11 int main() {
    12     LL n, m, k;
    13     cin >> n >> m >> k;
    14     m -= n;
    15     LL lcnt = k - 1, rcnt = n - k, l = 0, r = m, ans = 0;
    16     while(l <= r) {
    17         LL mid = (l + r) >> 1;
    18         LL tmp = mid;
    19         LL left, right;
    20         if(mid - lcnt < 1) { // 枚举的枕头数比左边的床数要少
    21             left = cal(1, mid - 1); // 从1开始,数量为枚举的枕头数-1
    22         } else left = cal(mid - lcnt, lcnt);
    23         if(mid - rcnt < 1) { // 同理
    24             right = cal(1LL, mid - 1);
    25         } else right = cal(mid - rcnt, rcnt);
    26         tmp += left + right;
    27         if(tmp > m) r = mid - 1;
    28         else { ans = mid; l = mid + 1; }
    29     }
    30     cout << ans + 1 <<endl; // 因为一开始已经每个床分配了一个枕头,所以要加回1
    31     return 0;
    32 }
  • 相关阅读:
    Linux多线程Pthread学习小结
    TCP三次握手/四次挥手
    内存管理内幕
    Delphi 中分发设计时包
    一个小的算法问题解决
    写了一个验证数字范围的正则表达式
    用 XML 文件持久化和恢复图片信息
    string.Empty 和 "" 并不总是可以互换的
    博客园用的 FreeTextBox 有 bug
    乱花渐欲迷人眼。。。
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6403140.html
Copyright © 2020-2023  润新知