0
点赞
收藏
分享

微信扫一扫

【刷题】codeforces Problem - 1661B Getting Zero

思考的鸿毛 2022-04-13 阅读 42
算法

题目链接

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来缩小问题规模的方法。网上搜索了一下好像还没有人贴这道题的思路,那么我就分享一下这题的方法,如果有大佬有更好的方法,希望能指点一下[合十]。欢迎大佬来交流~

举报

相关推荐

0 条评论