リンク:
https://vjudge.net/problem/CodeForces-916B
質問の意味:
ジェイミーはCodeforcesラウンドを準備しています。彼は問題のためにアイデアを持っているが、それを解決する方法を知りません。彼は次のような問題の解決策を書くのに役立ちます。
各番号の電源への2つの和が数nに等しく、回答最大の整数ができるだけ小さくなるように、k個の整数を見つけます。複数回答があるかもしれないとして、あなたは出力に辞書的に最大のものを求められます。
より明確にするために、長さk(A1、A2、...、AK)として、すべての整数列を考えます。各シーケンスに値を与えます。辞書最大で、出力は1最小のy値を持つすべての配列(単数または複数)のうち。
力と辞書順の定義についてはノートを参照してください。
アイデア:
最初にこの時間長がmより大きければ、それは可能でない、配列の最小数を構成している。
そうでなければ、より大きなフロント優先決意はすべて費やし、または小開始する減算することができません。
コード:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
//#include <memory.h>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <math.h>
#include <stack>
#include <string>
#include <assert.h>
#include <iomanip>
#define MINF 0x3f3f3f3f
using namespace std;
typedef long long LL;
LL n, m;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m;
multiset<int> st;
for (int i = 63;i >= 0;i--)
{
if ((1ULL<<i) <= n)
{
st.insert(i);
n -= (1LL<<i);
}
}
if (st.size() > m)
puts("No");
else
{
while (st.size() < m)
{
if (st.size() == 1)
{
int t = *st.rbegin();
st.erase(*st.rbegin());
st.insert(t-1);
st.insert(t-1);
}
else
{
int cnt = st.count(*st.rbegin());
if (m-st.size() >= cnt)
{
int t = *st.rbegin();
st.erase(t);
for (int i = 1;i <= cnt*2;i++)
st.insert(t-1);
}
else
{
int t = *st.begin();
t--;
st.erase(st.begin());
while (st.size()+2 < m)
{
st.insert(t);
t--;
}
st.insert(t);
st.insert(t);
}
}
}
cout << "Yes" << endl;
for (multiset<int>::reverse_iterator it = st.rbegin();it != st.rend();++it)
cout << *it << ' ';
cout << endl;
}
return 0;
}