题目链接
Getting Zero
题目大意:求最少的操作数
输入输出范例
input:
4
19 32764 10240 49
output:
14 4 4 15
解题思路
- 由于每个数的数据范围限制在32768,即 2 15 2^{15} 215,意味着每个数的操作数不会超过15。这里可以做一个限制。
-
v
v
v分为两部分:
v
=
v
c
l
o
s
e
+
v
r
e
s
t
v=v_{close}+v_{rest}
v=vclose+vrest
其中 v c l o s e v_{close} vclose是小于 v v v最大2的幂(eg. 小于19的最大2的幂为16), v r e s t = v % v c l o s e v_{rest}=v\% v_{close} vrest=v%vclose。原问题等价于求 v r e s t v_{rest} vrest 的最少操作数。 - 对于数 v v v而言,得到它的最小操作数有两个方向,一是向上,先执行加1操作,变成大于 v v v最小2的幂,然后由该幂转换为 2 15 2^{15} 215;二是向下,由于求解 v v v等价于求解 v r e s t v_{rest} vrest,可以将问题缩小至 v = 1 v=1 v=1 的情况。
Accepted 代码
#include<iostream>
using namespace std;
int n_close(int n){
int t=0;
for(int i=1;i<16;i++){
if((1<<i)>n&&(1<<t)<=n){
break;
}
else t=i;
}
return t;
}
int func(int n){
// n to 2**15
if(n==1)return 15;
int t=n_close(n);
int way1, way2, n2;
way1=min(15-(t+1)+((1<<(t+1))-n), 15);
n2=n%(1<<t);
if(n2==0)way2=15-t;
else way2=min(15, func(n2));
return min(way1, way2);
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
int num;
cin>>num;
if(i==n-1) cout<<func(num);
else cout<<func(num)<<" ";
}
return 0;
}
总结
也不是什么大佬,本菜鸡想了一个小时,才想出利用 v r e s t v_{rest} vrest来缩小问题规模的方法。网上搜索了一下好像还没有人贴这道题的思路,那么我就分享一下这题的方法,如果有大佬有更好的方法,希望能指点一下[合十]。欢迎大佬来交流~