题解:CF916B Jamie and Binary Sequence (changed after round)

题意

把一个数分解成恰好 k2ai 次方的和,可以重复,要求保证最大的 ai 要尽可能的小时,a 的字典序尽可能大,输出序列 a

分析

首先我们借助二进制拆出一个满足 n=2ai 序列 a,满足 a 的长度最小。

若此时 a 的长度大于 k,显然无解。

因为 2m=2m1+2m1,我们每次取出序列中最大的元素 ai,然后向序列中加入两个 ai1 直到序列的长度等于 k

因为我们每次拆出的元素均为序列中的最大值,显然能保证此时 maxai 是最小的。

模拟上述过程,然后得到 WA on #5。


k=5,而某一步得到的 a={4,4,2,1} 这种情况就能 hack 掉这种做法。

因为此时拆掉最大元素 4 得到的序列 a={4,3,3,2,1} 的字典序小于拆掉最小元素 1 得到的序列 a={4,4,2,0,0}

发现如果当前的 maxai 等于答案中的 maxai 时,拆掉最小元素的方案会使字典序大于拆掉最小元素的方案。

使用 set 模拟即可。

AC 记录

Code

#include<bits/stdc++.h>
using namespace std;
multiset<int, greater<int>> s, s0;
int main()
{
int64_t n, k;
cin>>n>>k;
for(int i=0;i<63;i++)
if(n&(1ll<<i)) s.emplace(i);
if(s.size()>k) return cout<<"No", 0;
cout<<"Yes\n";
s0=s;
while(s.size()<k)
{
int p=*s.begin();
s.erase(s.begin());
s.emplace(p-1);
s.emplace(p-1);
}
int mx=*s.begin();
while(s0.size()<k)
{
int p=*s0.begin();
if(p==mx) break;
s0.erase(s0.begin());
s0.emplace(p-1);
s0.emplace(p-1);
}
while(s0.size()<k)
{
int p=*s0.rbegin();
s0.erase(prev(s0.end()));
s0.emplace(p-1);
s0.emplace(p-1);
}
for(auto i:s0) cout<<i<<' ';
}

本文作者:Jimmy-LEEE

本文链接:https://www.cnblogs.com/redacted-area/p/18389458

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Jimmy-LEEE  阅读(5)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起