Codeforces Round #596 Div. 2 C. p-binary

题目连接:C. p-binary
Codeforces Round #596 Div. 2 C. p-binary_第1张图片
Codeforces Round #596 Div. 2 C. p-binary_第2张图片

思路:

n = (2^x1 + p) + (2^x2 + p ) + …

转换一下把右边的所有p移到左边:

n - p * cnt = 2^x1 + 2^x2 + 2^x3;

枚举cnt,从1开始,边界是 (n - p * cnt) > 0,因为右边 > 0;

设 x = n - cnt * p;计算 x 的二进制下有几个1,如果1的个数 <= cnt 并且 x 是 >= cnt 的,说明cnt就是最小的解

因为:

第一:把任意一个数转成二进制,例如 t = 1011 即 t = 2^0 + 2^1 + 2^3,可以看出每一项都不同,所以如果1的个数>cnt 的话,是不可能匹配的;

至于小于等于就可以是因为可以合并即 2^2 + 2^2 = 2^3

第二:x 必须大于等于cnt,由于是2的次方,即右边最小值就是cnt个2^0 = cnt,所以x 必须 大于等于 cnt.

/****************************
Author: hbb
Create: 2019-10-27 12:43:53
 ****************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 2e6 + 5;
const int mod = 1e9 + 7;
const int inf = INT_MAX >> 1;
typedef long long int LL;

int main(){
	int n, p;
	while(scanf("%d %d", &n, &p) != EOF){
		int ans = -1;
		for(int i = 1; i <= 35; i++){
			int num = n - i * p;
			if(num <= 0) break;
			int cnt = 0;
			while(num){
				if(num & 1) cnt++;
				num >>= 1;
			}
			num = n - i * p;
			if(cnt <= i && i <= num){
				//printf("i = %d\n", i);
				ans = i;
				break;
			}
		}
		printf("%d\n", ans);
	}
}

你可能感兴趣的:(题解)