Make a Power of Two(D)

D. Make a Power of Two
题意:给你一个数n,可以有两种操作:删除n中任意一位上的数,向右加一位数。可执行多次操作,最后所得数必须是2的幂次数,求最少要操作几步。

题目有点忽悠人,一看这题总觉得似成相识,觉得找2的幂就应该变成二进制找规律。好吧,是我想多了,可能我对这种题的套路还不是很敏感,长个记性吧。
分析过程有点繁琐,直接去看粗体字就行。

既然题目问最少操作几步就肯定有一个上限卡住(没为什么),所以先找上限,可以想到1个数如果变成2的幂次数最多可以直接删除这个数然后加一个2的幂次数,不妨让这个二的幂次数就是1,所以最少操作步数的上限应该控制为这个数的位数加1(操作:全删除再加1)。
因为这个数可以变成任意二的幂次数,以1052为例,二的幂次数从1开始枚举,1、2、4、8、16、32、64、128…。
•四位数变成一位数:可以先删除3位变成一个一位数,看这一位数是否是二的幂,是则停止,不是则删除这一位数再加上“1”这一位。例如1052,删除0、5、2,留1,操作4-1=3步,或者删除1、0、2留5,再把5去了加上“1”(1052->1,这里也可以变成2或者4或者8),操作4-1+2=5步(也就是上限)
•四位数变成两位数:四位数变成二位数,先删除任意两位变成一个两位数,然后找二的幂次数里的两位数,如果相等则停止,如果只有一位数一样就删一位添一位,如果两位都不一样,就都删了新加这个二位数。例如1052,可以删除5和2,1052->10,10如果变成16,删“0”添“6”,操作4-2-1+2=3步,或者10如果变成32,操作4-2+2+2=4步。
变三位数,变四位数同理。
总结一下,一个数有n位,变成一个m位数(二的幂次数),进行的操作,首先这个数变成任意m位数要删除n-m个数,然后找该数与你要变成的数有几位是不一样的,比如x位是不一样的,替换这x位数字,也就是删除再添加,每一位都需要进行两步操作,操作步数为n-m+2*x(注意:原n位数如果需要全部替换,考虑上限,n位数变成一位数即可)

#include<iostream>
using namespace std;
typedef long long ll;
int a[20],b[20],x,y,ans;
int main()
{
    
    
    int t,n;
    cin>>t;
    while(t--)
    {
    
    
        cin>>n;
        x=1;
        while(n)
        {
    
       a[x++]=n%10;
            n/=10;
        }
        ans=x;
        for(ll i=1; i<=1e18; i*=2)
        {
    
    
            ll p=i;
            y=1;
            while(p)
            {
    
    
                b[y++]=p%10;
                p/=10;
            }
            int m=y-1;
            for(int j=x-1; j; j--)
            {
    
    
                if(m&&b[m]==a[j])
                    m--;
            }
            ans=min(ans,(x-1)-(y-1)+2*m);
        }
        cout<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_51443397/article/details/119823803