题目大意
如果一个数
x
x
x能表示成
2
m
+
k
2^m + k
2m+k的形式,则称它为好数。
给出一个数
n
n
n和参数
k
k
k,问
n
n
n最少能用多少个好数表示,可以用相同的好数表示。
如果无法表示,则输出-1
时间限制
2s
数据范围
n ≤ 1 0 9 n\le10^9 n≤109
题解
不妨把
n
=
(
2
m
1
+
k
)
+
(
2
m
2
+
k
)
+
⋯
+
(
2
m
p
+
k
)
n=\pod{2^{m_1}+k}+\pod{2^{m_2}+k}+\cdots+\pod{2^{m_p}+k}
n=(2m1+k)+(2m2+k)+⋯+(2mp+k)
即
n
=
2
m
1
+
2
m
2
+
⋯
+
2
m
p
+
k
×
p
n=2^{m_1}+2^{m_2}+\cdots+2^{m_p}+k\times p
n=2m1+2m2+⋯+2mp+k×p
则显然可以枚举
p
p
p,
然后就可以在
O
(
log
n
)
O(\log n)
O(logn)内判断。
Code
//#pragma GCC optimize (2)
//#pragma G++ optimize (2)
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#include <vector>
#include <queue>
#define G getchar
#define ll long long
using namespace std;
ll read()
{
char ch;
for(ch = G();(ch < '0' || ch > '9') && ch != '-';ch = G());
ll n = 0 , w;
if (ch == '-')
{
w = -1;
ch = G();
} else w = 1;
for(;'0' <= ch && ch <= '9';ch = G())n = (n<<1)+(n<<3)+ch-48;
return n * w;
}
const int N = 2003;
const int mo = 998244353;
int n , p , ans;
int calc(int x)
{
int s = 0;
for ( ; x ; )
{
if (x & 1) s++;
x = x >> 1;
}
return s;
}
int main()
{
//freopen("b.in","r",stdin);
//freopen("2.txt","w",stdout);
n = read();
p = read();
ans = -1;
for (int i = 1 ; i < 45 ; i++)
if ((n - p * i >= i) && calc(n - p * i) <= i)
{
ans = i;
break;
}
printf("%d\n", ans);
}