https://codeforces.com/contest/1247/problem/C
題意就不說了;
題解:首先先看n的範圍在1e9之內,p的範圍在-1000~1000, 然後問題求解的是滿足條件的最小數量的2的次冪的個數,則打表看出>1e9了,並且就可以拆成這個值這麼多大子集個數,所以在30內枚舉用了多少個P,再去 check 這個N值二進制有多少1,比較就好了,注意拆。
細節:當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;
}