嘘~ 正在从服务器偷取页面 . . .

洛谷P2431 正妹吃月饼 题解


洛谷P2431 正妹吃月饼 题解

题目链接:P2431 正妹吃月饼

题意

今天是中秋节。uim 带来了一堆大小不同且味道各异的月饼。

这些月饼的质量分别是 1g,2g,4g,8g,16g ... 后面一个是前面的2倍。每种只有一个。

uim让正妹随便吃。

正妹希望尝试尽可能多的口味,所以会吃尽可能多数量的月饼(不是重量)。而且她的确有些饿了,至少总共要吃掉 \(A\) g的月饼才能满足。

然而正妹怕长胖,所以吃月饼不能合计超过 \(B\) g。

她希望知道自己最多能吃多少个月饼

输入格式

两个数,\(A,B\)

输出格式

正妹能吃到最多的数量

数据范围

\(1 \le A,B \le 2^{63}-1\)

先吃块月饼再来写题解

显然我们会优先吃质量小的月饼。

但是怎么吃能保证正好在 \([A,B]\) 间呢?

不难发现,如果要吃满 \(A\) ,能获得的最大价值就是 \(\mathrm{popc}(A)\)

这里 \(\mathrm{popc}(x)\) 表示 \(x\) 在二进制下的 \(1\) 的个数。

证明很简单(其实靠直觉看的出来)

如果想尽可能吃小的,你会发现你不得不吃掉 \(A\) 二进制下最高位那个 \(1\) ,不然你到不了 \(A\)

所以我们只要从 \(A\) 开始从小到大一个一个(警觉)吃即可。

时间复杂度 \(\mathcal{O}(1)\)

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)())

int a,b,c,d;
unsigned int t;
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    
    cin >> a >> b; c=((1ll << 62) - 1) ^ a;
    d = __builtin_popcountll(a);
    for(; c; c-=t) if(a + (t=c&(-c)) <= b) a+=t, ++d; else break;
    cout << d << '\n';
    return 0;
}

文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录