题目大意
给定一个 n , k n,k n,k,有一个数列 2 0 , 2 1 , 2 2 , 2 3 , . . . 2^0,2^1,2^2,2^3,... 20,21,22,23,...,第 i i i 个数为 2 i − 1 2^{i-1} 2i−1。
特别的,若第 k k k 个数, 2 k − 1 ≥ k 2^{k-1} \ge k 2k−1≥k,就将第 k k k 个数改为 k k k。
若这个数列前 q q q 个数的和 ≤ n < \leq n < ≤n< 这个数列前 q + 1 q+1 q+1 个数的和, q + 1 q+1 q+1 即为答案。
输出答案 q + 1 q+1 q+1。
T T T 组数据。
1 ≤ T ≤ 1 0 5 1≤T≤10^5 1≤T≤105, 1 ≤ k ≤ n ≤ 1 0 18 1 \leq k \leq n \leq 10^{18} 1≤k≤n≤1018。
解题思路
很明显了。
模拟即可。
最后结果为
⌈
n
−
2
m
k
⌉
+
m
(
2
m
−
1
≤
k
<
2
m
,
2
m
≤
n
)
\lceil \frac{n - 2^m}{k} \rceil + m (2^{m-1}\leq k < 2^m,2^m \leq n)
⌈kn−2m⌉+m(2m−1≤k<2m,2m≤n)
时间复杂度
O
(
64
T
)
\mathcal{O}(64T)
O(64T)。
CODE
#include <cstdio>
using namespace std;
int T;
long long n, k;
signed main()
{
scanf("%d", &T);
while(T--)
{
scanf("%lld%lld", &n, &k);
if(n == 1)
{
printf("0\n");
continue;
}
if(k == 1)
{
printf("%lld\n", n - 1);
continue;
}
long long b = 1, cnt = 0;
while(b <= k && b * 2 <= n)
{
b *= 2;
cnt++;
}
n -= b;
cnt += n / k + (n % k == 0 ? 0 : 1);
printf("%lld\n", cnt);
}
return 0;
}