Codeforces Round #596 C. p-binary(思維)

https://codeforces.com/contest/1247/problem/C

題意就不說了;

題解:首先先看n的範圍在1e9之內,p的範圍在-1000~1000, 然後問題求解的是滿足條件的最小數量的2的次冪的個數,則打表看出2^{30}>1e9了,並且2^{x}就可以拆成這個值這麼多大子集個數,所以在30內枚舉用了多少個P,再去 check 這個N值二進制有多少1,比較就好了,注意拆2^{x}

細節:當N的二進制個數<枚舉的P的個數的時候,肯定不滿足條件了。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e6 + 5;
const int INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
ll n,p;
ll w;
ll pow(int a,int b){
	ll ans=1;
	while(b){
		if(b&1) ans=a*ans;
		a=a*a;
		b=b/2;
	}
	return ans;
}
int check(ll x){//二進制有多少個1 
	int ans=0;
	w=1;
	while(x){
	  if(x%2==1) ans++;
	  x=x/2;
	  w=w*2;
	}
	w=w/2;
	return ans;
}
int main(){
	
//	for(int i=0;i<=40;i++){
//		ll pp=pow(2,i);
//		cout<<i<<" "<<pp<<endl;
//	}
	cin>>n>>p;
	int ans=INF;
	int tmp;
	if(p==0){
	    tmp=check(n);
	    ans=min(ans,tmp);
	}else{
		for(int i=1;i<=30;i++){
			ll k=i*p;
			ll N=n-k;
			if(N<0) break;
			int tmp=check(N);
	        if(i==tmp) ans=min(ans,i);
	        else if(i>tmp){
	        	if(w==1){//不能拆成小的子集了 
	        		if(i==1) ans=min(ans,i);
				}
	        	else if(i<=w)//拆成小的子集 
				   ans=min(ans,i);
			}  
		}
    }
	if(ans==INF) ans=-1;
	cout<<ans<<endl;
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章