• [原创]公平数的解法


    公平数题解

    百度之星的题目,是分值最多的,感觉不是很难,倒是分少的好难。

    公平数 (35分)
    问题背景
    如果一个整数的十六进制表示(不含前导0)中,前一半数字之和等于后一半数字之和,我们称它为公平数。
    注意,如果该数的十六进制表示中包含奇数个数字,则正中间的数字既不属于前一半,又不属于后一半。

    例如在十六进制下1+D=7+7,因此1DE77是公平数。数字E并不参与计算。
    再例如,所有单个数字的十六进制数(即0~F)均为公平数,但F0不是(不能把F0补充前导0写成0F0,进而认为它是公平数)。

    给出十六进制数 K, X, Y 和十六进制数字集合 S,求区间[X, Y]之内,有多少个公平数满足:

    十六进制表达式(不包含前导0)中每个数字均在集合S中
    并且为K的倍数

    输入格式
    输入第一行为数字集S,包含0~9以及大写字母A~F。
    每个数字或字母最多出现一次。
    第二行包含 3 个十六进制正整数K, X, Y,均不超过 10 个数字(包含0~9以及大写字母A~F,不包含前导 0)。

    输出格式
    仅一行,包含一个整数,即满足条件的公平数个数。

    样例输入
    124C
    5 100 FFF

    样例输出
    4

    样例解释
    只有四个数满足条件:212,424,4C4,C1C。

    题解主要代码如下:

    char int2char(int a)
    {
        char b;
        if(a<=9&&a>=0)
            b=a+'0';
        else if(a>=10&&a<=15)
            b=a+'A'-10;
        else
            b=0;
        return b;
    }

    //求十六进制整数字符长度
    int length(int i)
    {
        char buff[11];
        sprintf(buff,"%x",i);
        string si(buff);
        return si.length();
    }

    //判断十六进制数字的字符是否都在字符集中
    bool inset(int i,string charset)
    {
        int j;
        while(i!=0)
        {
            int num = i%16;
            int pos = charset.find(int2char(num));
            if(pos==-1)
                return false;
            i /= 16;
        }
        return true;
    }

    //改进版如下,该版本除了判断该16进制数的字符是否为字符集中的外,还会寻找下一个可能的数字

    //由于如果某高位不是字符集的字符,那么所有含该高位的数都是不符合的,因此下一个可能的数就是直接将该高位加1得到//的数(低于该位的数归零)

    bool inset(long temp,string charset,long& i)
    {
        int j=0;
        int highest=0;
        while(temp!=0)
        {
            ++j;
            int num = temp%16;
            int pos = charset.find(int2char(num));
            if(pos==-1)
                highest = j;
            temp /= 16;
        }
        if(highest==0)
            return true;
        else
        {
            temp = i;
            for(j=0;j<highest-1;j++)
            {
                i = i - temp%16*pow(16,j);
                temp /= 16;
            }
            i = i + pow(16,highest-1);
            return false;
        }
    }
    int main(int argc, char* argv[])
    {
        string charset;
        int k,x,y;
        cin>>charset;
        scanf("%x %x %x",&k,&x,&y);
        sort(charset.begin(),charset.end());
        int i,j,sum=0;
        while(x%k!=0)
            ++x;
        for(i=x;i<=y;i+=k)
        {
            int temp = i;
            if(inset(temp,charset))//改进版改为inset(temp,charset,i)
            {
                int len = length(temp);
                int rsum=0,lsum=0;
                if(len!=1)
                {
                    for(j=0;j<len/2;j++)
                    {
                        rsum += temp%16;
                        temp /= 16;
                    }
                    if(len%2!=0)
                        temp /= 16;
                    for(j=0;j<len/2;j++)
                    {
                        lsum += temp%16;
                        temp /= 16;
                    }
                    if(rsum==lsum)
                    {
                        sum++;
                        printf("%x\t",i);
                    }
                }
                else
                {
                    sum++;
                }
            }

            //改进版添加才需要如下代码

            else
            {
                while(i%k!=0)
                    i++;
                i -= k;
            }

        }
        cout<<sum<<endl;

        return 0;
    }

  • 相关阅读:
    远程培训数据库迁移
    RMAN系列catalog数据库
    RMAN系列表空间恢复
    典型的一周备份脚本
    [转载]对 Oracle 备份与恢复 的补充说明转自tianlesoft的文章
    RMAN系列基于scn恢复
    使用Profile对用户Session会话进行资源限制
    RMAN系列控制文件、数据文件、redolog全部丢失
    全自动 TSPITR基于RMANLOGSEQ
    Oracle 10g EXPDP和IMPDP使用说明
  • 原文地址:https://www.cnblogs.com/absolute8511/p/1649586.html
Copyright © 2020-2023  润新知