题意:给两个数 nnpp,定义 p-binary 数为 22 的幂加上 pp 的数,例如:20+p,21+p,22+p2 ^{0} +p,2 ^{1} +p,2 ^{2} +p,将 nn 拆分成若干个 p-binary 数,求出拆分得到的最少 p-binary 数,如果无解输出 1-1

假设 nn 被拆成 mmp-binary 数,那么有如下式子:

nmp=2x1+2x2++2xm n-mp={ 2^ {x _1} }+{ 2^ {x _2} }+···+{ 2^ {x _m} }

很明显,我们可以从小到大枚举 nmpn-mp,对于每一个枚举的数用二进制表示,把其中 11 的个数记为 qq

如果 qmq\leq m ,并且 nmpmn-mp\geq m,那么此时 mm 就是答案。

证明:如果 q=mq=m ,那么正好可以拆分成 mm 个数,显然满足,如果 q<mq<m ,那么我们可以将较大的 22 的幂分成两个较小的 22 的幂,例如 2x=2x1+2x12^ {x}={2^ {x-1} }+{2^ {x-1} },可以凑成 mm 个数,其次由 nmp=2x1+2x2+2xmn-mp={2^ {x _1 } }+{2^ {x _2 } }···+{2^ {x _m } } 可知,右边的式子肯定大于等于 mm,所以左边的式子也要满足大于等于 mm

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
int n,p,ans=1;
int clac(int x)
{
	int sum=0;
	while(x)
	{
		if(x&1)
			sum++;
		x>>=1;
	}
	return sum;
}
int main()
{
	scanf("%d%d",&n,&p);
	while(n-ans*p>=ans)
	{
		int x=n-ans*p;
		int num=clac(x);
		if(num<=ans)
		{
			printf("%d",ans);
			return 0;
		}
		ans++;
	}
	printf("-1");
	return 0;
}