CF1095C Powers Of Two(バイナリ分割/ STL優先キュー)

タイトル説明

プログラマーとして、趙氏は本当に二元系が好きな
ので、多くの彼はそんなに2のべき乗を好きだ。彼は
彼が正の整数かどうかを把握nは2のべき乗のk個の合計に分けることができます助けるためにあなたを望んでいる
入力
の最初の行があり2つの正の整数n、kのみ(1≤n≤10^ 9、1≤k≤2・10 ^ 5)。

出力
そのようなスキームがない場合は、NOを出力します。

それ以外の場合は、YESを出力し、k個の正の整数を出力します。それらの合計はnです。複数のスキームがある場合は、いずれか1つを出力します。

例として
、入力
9 4
出力
YES
1 2 2 4
入力
8 1
出力
YES
8
入力
5 1
出力
NO
入力
3~7
出力
NO

問題分析:

例としてn = 5、k = 3を取り、(101)のようにバイナリに分割します。この時点で2つの1があります。つまり、4 + 1は少なくとも2つに分割できますが、k = 3、

性質によると2n = 2 n-1 * 2

バイナリ(101)を最上位ビットから次のビット(021)に分割し、それを2+ 2 +1の3つの部分に分割できます。

最大から最小に配置された優先度キューを使用して、4と1をキューに入れ、最も高いビットを順番に取り出し、次に2つの最も高いビットを2で除算して、sum = kであることがわかっている状態で再びキューに入れることができます。満足している;

ACcode


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define  gold_m main
using namespace std;
typedef long long ll;
const int N=1e6+10;
ll a[N];
int gold_m() {
    
    

	ll n,k;

	cin>>n>>k;
	if(n==0&&k==0||k>n) {
    
    
		cout<<"NO";
		return 0;
	}
	ll cnt=1,sum=0;
	priority_queue<ll,vector<ll>,less<ll>>heap;
	while(n>0) {
    
    
		if(n%2)
			heap.push(n%2*cnt);
		if(n%2) sum++;
		cnt*=2;
		n/=2;
	}
	if(sum>k) {
    
    
		cout<<"NO";
		return 0;
	}
	cout<<"YES"<<endl;
	while(heap.size()<k) {
    
    
		ll temp=heap.top();
		heap.pop();
		if(temp>=2) {
    
    
			heap.push(temp/2);
			heap.push(temp/2);
		}
	}
	while(!heap.empty()) {
    
    
		cout<<heap.top()<<" ";
		heap.pop();
	}


	return 0;
}

STLを使用しない別の方法

同じ考え

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define  gold_m main
using namespace std;
typedef long long ll;
const int N=1e6+10;
ll a[N];
int gold_m() {
    
    
	ll n,k;
	cin>>n>>k;
	if(n==0&&k==0||k>n) {
    
    
		cout<<"NO";
		return 0;
	}
	ll cnt=0,sum=0;
	while(n>0) {
    
    
		a[++cnt]=n%2;
		if(n%2) sum++;
		n/=2;
	}
	ll t= cnt;
	// 从高位cnt开始
	while(sum<k) {
    
    
		if(cnt==1)
			break;
		if(a[cnt]) {
    
    
			a[cnt]--;
			a[cnt-1]+=2;
		} else {
    
    
			cnt--;
		}
		if(a[cnt])
			sum++;
	}

	if(sum!=k) {
    
    
		cout<<"NO";
		return 0;
	}
	cout<<"YES"<<endl;
	ll temp=1;
	for(int i=1 ; i<=t; i++) {
    
    
		for(int j=1; j<=a[i]; j++)
			cout<<temp<<" ";
		temp*=2;
	}


	return 0;
}



おすすめ

転載: blog.csdn.net/wmy0536/article/details/104091120