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;
}