首先我们要知道这题不存在无解情况(子弹是无限的)
然后根据题目的2^20考虑到二进制
举个例子先:
5 = 101
10 = 5 * 2 = 1010
不难发现当一个数乘以2之后,相当于在这个数的二进制末尾添加了一个0
而能被2^20整除的条件就是这个数拆分成二进制后,第一个1出现在第20位之前
所以答案必然在20以内(就算第一位是1,最差情况这个数乘以20次2后也能被2^20整除)
然后讨论特例,比如7 = 111,我们可以发现7 + 1 = 8 = 1000,如果我们直接让7乘以20次2明显比7 + 1再乘以17次2次数更多
所以我们可以枚举n + 0到n + 20的所有情况进行比较,找出最小的操作次数
下面是我的代码,写的很答辩凑合看看吧(跑
#include <bits/stdc++.h>
using i64 = long long;
#define int long long
void solve(){
int n, ans = 1e18;//ans = 20是一样的,不影响
std::cin >> n;
if(n >= (1ll << 20)){
if(n % (1ll << 20) == 0){
std::cout << 0 << '\n';
return;
}else{
n %= (1ll << 20);
for(int i = 0; i <= 20; ++i){
int tt = n + i, cnt = 0;
while(tt % 2 == 0){
tt /= 2;
cnt++;
}
ans = std::min({20 - cnt + i, (1ll << 20) - n, ans});
}
}
}else{
for(int i = 0; i <= 20; ++i){
int tt = n + i, cnt = 0;
while(tt % 2 == 0){
tt /= 2;
cnt++;
}
ans = std::min({ans, 20 - cnt + i, (1ll << 20) - n});
}
}
std::cout << ans << '\n';
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr), std::cout.tie(nullptr);
i64 _ = 1;
std::cin >> _;
while (_--) {
solve();
}
return 0;
}