题解 CF9C 【Hexadecimal's Numbers】

思路

这个题目据可以有两种思路,一种是递归构造答案的方法,一种是使用公式计算的的方法。第一种方法就是楼下个位大佬的做法,就是对于1,我们如果要的到后面的两组答案,一种是对这个数乘10,或是乘10后加一,这样就得到了新的两种答案,我们在对新的答案这样递归求解下去,直到大于输入的数 $ n $ 为止,这样我们在一边递归的时候一边记录的到的新数的数量,就可以解决这个问题了。

但是其实还有另一种方法,这个方法稍微慢一点,就是我们先求出不大于 $ n $ 的一个最大的只由 0,1 组成的数我们要怎么求这个数呢。废话不说上代码:

scanf("%lld",& n);
    //将这个数的每一位分解
    while(n!=0){
        num.push_back(n%10);
        n/=10;
    }

    for(int i=num.size()-1;i>=0;i--){
        if(num[i]>1) //如果这个位子上的数大于1了,那么我们要求的那个数之后的几位就全是1了
            flag=true;
        if(flag)
            maxn.push_back(1);
        else{ //由于不能让所求的数超过n所以为了让这个数尽量大,如果是1的地方就是1,不是1的地方就是0,这样所求的数就不会超过原来的数
            if(num[i]==1)
                maxn.push_back(1);
            else
                maxn.push_back(0);
        }
    }

假如我们有一个10013027那么我们之后得到的数就是10011111,之后我们发现我们只需要对这个数进行一些1变成0或0变成1之类或者什么操作都不做的操作就可以得到我们想要的答案。对于例子中得到的数10011111,假如我们让第一个1变成0,那么后面的数不管进行什么操作的到的数一定是小于例子中的得到的数的,所以我们假设当前位置为i那么我们就可以用2^(len-i)去更新答案 len 就是那个得到的数的长度。

Ps:这个算法这么解释有些地方其实是不对的,但是这些地方难以用言语解释清楚,所以你们可以自己去证明,但是这个思路的大体方向就是这样没错的。如果你想让程序跑得更快,可以用快速幂来优化。

完整代码:

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

bool flag=false;
long long n;
vector <int> num,maxn; //注意:maxn是反过来存的

long long power(long long x,long long y)
{
    long long ans=1,base=x;
    while(y!=0){
        if(y&1)
            ans=ans*base;
        base=base*base;
        y>>=1;
    }
    return ans;
}

int main()
{
    scanf("%lld",& n);
    while(n!=0){
        num.push_back(n%10);
        n/=10;
    }

    for(int i=num.size()-1;i>=0;i--){
        if(num[i]>1)
            flag=true;
        if(flag)
            maxn.push_back(1);
        else{
            if(num[i]==1)
                maxn.push_back(1);
            else
                maxn.push_back(0);
        }
    }

    long long ans=0;
    for(register int i=0;i<(int)maxn.size();i++){
        if(maxn[i]==1){
            ans+=power(2,(int)maxn.size()-1-i);
        }
    }

    printf("%lld\n",ans);

    return 0;
}

转载于:https://www.cnblogs.com/lixiao189/p/9533993.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值