题意
题目链接
给你一个数
v
v
v,在每步操作中,你可以:
让
v
=
(
v
+
1
)
v=(v+1)
v=(v+1)
m
o
d
mod
mod
32768
32768
32768
或者让
v
=
(
2
⋅
v
)
v=(2·v)
v=(2⋅v)
m
o
d
mod
mod
32768
32768
32768
问使得
v
=
0
v=0
v=0的最小操作数,其中
0
≤
v
<
32768
0≤v<32768
0≤v<32768。
思路
由于 32768 = 2 15 32768={2}^{15} 32768=215,则考虑 v v v的二进制数,那么 v = ( 2 ⋅ v ) v=(2·v) v=(2⋅v) m o d mod mod 32768 32768 32768的操作等价于 v = ( v < < 1 ) v=(v<<1) v=(v<<1) a n d and and ( ( 1 < < 16 ) − 1 ) ((1<<16)-1) ((1<<16)−1),当 v = 32768 = ( 1 < < 15 ) v=32768=(1<<15) v=32768=(1<<15)时 v = 0 v=0 v=0。因此最大操作数不超过 15 15 15。
对于 v v v的二进制数,加若干个 1 1 1后再乘若干个 2 2 2达到 32768 32768 32768。因此直接暴力求出在最大操作数不超过 15 15 15的所有情况中的最小操作数即可。
注意特判当 v = 0 v=0 v=0的情况,此时直接输出 0 0 0即可。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 32768 + 5;
ll n, a[maxn];
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;
for(ll i=1;i<=n;i++){
cin>>a[i];
ll ans = 1e9;
for(ll j=0;j<=15;j++){
ll x = a[i], curans = j;
x+=j;
for(ll k=1;k<=15;k++){
if(x==32768||x==0)break;
x = x << 1;
x = x&((1LL<<16)-1);
curans++;
}
ans=min(ans,curans);
}
cout<<ans<<" ";
}
return 0;
}
总结
想到二进制数操作后,还要考虑到加操作使得最低位的 1 1 1进多少位的问题,因此要暴力求解所有可能的加操作数。此外,注意特判。